mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-28 06:05:58 -04:00
Merge pull request #1118 from paulromano/data-updates
Allow WMP in cross_sections.xml, other data updates
This commit is contained in:
commit
a73b328ffd
79 changed files with 1377 additions and 1330 deletions
|
|
@ -15,11 +15,12 @@ addons:
|
|||
- libhdf5-mpich-dev
|
||||
- libblas-dev
|
||||
- liblapack-dev
|
||||
config:
|
||||
retries: true
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/nndc_hdf5
|
||||
- $HOME/endf-b-vii.1
|
||||
- $HOME/WMP_Library
|
||||
env:
|
||||
global:
|
||||
- FC=gfortran
|
||||
|
|
@ -28,7 +29,6 @@ env:
|
|||
- OMP_NUM_THREADS=2
|
||||
- OPENMC_CROSS_SECTIONS=$HOME/nndc_hdf5/cross_sections.xml
|
||||
- OPENMC_ENDF_DATA=$HOME/endf-b-vii.1
|
||||
- OPENMC_MULTIPOLE_LIBRARY=$HOME/WMP_Library
|
||||
- LD_LIBRARY_PATH=$HOME/MOAB/lib:$HOME/DAGMC/lib
|
||||
- PATH=$PATH:$HOME/NJOY2016/build
|
||||
- DISPLAY=:99.0
|
||||
|
|
@ -39,7 +39,7 @@ env:
|
|||
- OMP=n MPI=y PHDF5=n
|
||||
- OMP=n MPI=y PHDF5=y
|
||||
- OMP=n MPI=y PHDF5=y DAGMC=y
|
||||
- OMP=y MPI=y PHDF5=y DAGMC=y
|
||||
- OMP=y MPI=y PHDF5=y DAGMC=y
|
||||
notifications:
|
||||
webhooks: https://coveralls.io/webhook?repo_token=$COVERALLS_REPO_TOKEN
|
||||
install:
|
||||
|
|
|
|||
|
|
@ -384,6 +384,7 @@ add_library(libopenmc SHARED
|
|||
src/dagmc.cpp
|
||||
src/cell.cpp
|
||||
src/cmfd_execute.cpp
|
||||
src/cross_sections.cpp
|
||||
src/distribution.cpp
|
||||
src/distribution_angle.cpp
|
||||
src/distribution_energy.cpp
|
||||
|
|
@ -425,7 +426,7 @@ add_library(libopenmc SHARED
|
|||
src/simulation.cpp
|
||||
src/source.cpp
|
||||
src/state_point.cpp
|
||||
src/string_functions.cpp
|
||||
src/string_utils.cpp
|
||||
src/summary.cpp
|
||||
src/surface.cpp
|
||||
src/tallies/filter.cpp
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ 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_MULTIPOLE_LIBRARY=/root/WMP_Library \
|
||||
OPENMC_ENDF_DATA=/root/endf-b-vii.1
|
||||
|
||||
# Install dependencies from Debian package manager
|
||||
|
|
@ -36,4 +35,4 @@ RUN git clone https://github.com/openmc-dev/openmc.git /opt/openmc && \
|
|||
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
|
||||
RUN ./opt/openmc/tools/ci/download-xs.sh
|
||||
|
|
|
|||
|
|
@ -333,12 +333,14 @@ Functions
|
|||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_material_set_density(int32_t index, double density)
|
||||
.. 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 in atom/b-cm
|
||||
: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
|
||||
|
||||
|
|
|
|||
|
|
@ -30,11 +30,11 @@ or using pip (recommended)::
|
|||
pip install -e .[test]
|
||||
|
||||
It is also assumed that you have cross section data available that is pointed to
|
||||
by the :envvar:`OPENMC_CROSS_SECTIONS` and :envvar:`OPENMC_MULTIPOLE_LIBRARY`
|
||||
environment variables. Furthermore, to run unit tests for the :mod:`openmc.data`
|
||||
module, it is necessary to have ENDF/B-VII.1 data available and pointed to by
|
||||
the :envvar:`OPENMC_ENDF_DATA` environment variable. All data sources can be
|
||||
obtained using the ``tools/ci/travis-before-script.sh`` script.
|
||||
by the :envvar:`OPENMC_CROSS_SECTIONS` environment variables. Furthermore, to
|
||||
run unit tests for the :mod:`openmc.data` module, it is necessary to have
|
||||
ENDF/B-VII.1 data available and pointed to by the :envvar:`OPENMC_ENDF_DATA`
|
||||
environment variable. All data sources can be obtained using the
|
||||
``tools/ci/travis-before-script.sh`` script.
|
||||
|
||||
To execute the test suite, go to the ``tests/`` directory and run::
|
||||
|
||||
|
|
|
|||
|
|
@ -25,9 +25,10 @@ node. For example,
|
|||
``<library>`` Element
|
||||
---------------------
|
||||
|
||||
The ``<library>`` element indicates where an HDF5 cross section file is located,
|
||||
whether it contains incident neutron or thermal scattering data, and what
|
||||
materials are listed within. It has the following attributes:
|
||||
The ``<library>`` 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:
|
||||
|
||||
|
|
@ -48,4 +49,5 @@ materials are listed within. It has the following attributes:
|
|||
directory containing the ``cross_sections.xml`` file.
|
||||
|
||||
:type:
|
||||
The type of data contained in the file, either 'neutron' or 'thermal'.
|
||||
The type of data contained in the file. Accepted values are 'neutron',
|
||||
'thermal', 'photon', and 'wmp'.
|
||||
|
|
|
|||
|
|
@ -18,21 +18,6 @@ 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.
|
||||
|
||||
.. _multipole_library:
|
||||
|
||||
-------------------------------
|
||||
``<multipole_library>`` Element
|
||||
-------------------------------
|
||||
|
||||
The ``<multipole_library>`` element indicates the directory containing a
|
||||
windowed multipole library. If a windowed multipole library is available,
|
||||
OpenMC can use it for on-the-fly Doppler-broadening of resolved resonance range
|
||||
cross sections. If this element is absent from the settings.xml file, the
|
||||
:envvar:`OPENMC_MULTIPOLE_LIBRARY` environment variable will be used.
|
||||
|
||||
.. note:: The <temperature_multipole> element must also be set to "true" for
|
||||
windowed multipole functionality.
|
||||
|
||||
.. _material:
|
||||
|
||||
----------------------
|
||||
|
|
|
|||
|
|
@ -41,11 +41,6 @@ following environment variables are used:
|
|||
user has not specified :attr:`Materials.cross_sections` (equivalently, the
|
||||
:ref:`cross_sections` in :ref:`materials.xml <io_materials>`).
|
||||
|
||||
:envvar:`OPENMC_MULTIPOLE_LIBRARY`
|
||||
Indicates the path to a directory containing windowed multipole data if the
|
||||
user has not specified :attr:`Materials.multipole_library` (equivalently, the
|
||||
:ref:`multipole_library` in :ref:`materials.xml <io_materials>`)
|
||||
|
||||
:envvar:`OPENMC_MG_CROSS_SECTIONS`
|
||||
Indicates the path to the an :ref:`HDF5 file <io_mgxs_library>` that contains
|
||||
multi-group cross sections if the user has not specified
|
||||
|
|
@ -306,12 +301,12 @@ Windowed Multipole Data
|
|||
-----------------------
|
||||
|
||||
OpenMC is capable of using windowed multipole data for on-the-fly Doppler
|
||||
broadening. While such data is not yet available for all nuclides, an
|
||||
experimental multipole library is available that contains data for 70
|
||||
nuclides. To obtain this library, you can run :ref:`scripts_multipole` which
|
||||
will download and extract it into a ``wmp`` directory. Once the library has been
|
||||
downloaded, set the :envvar:`OPENMC_MULTIPOLE_LIBRARY` environment variable (or
|
||||
the :attr:`Materials.multipole_library` attribute) to the ``wmp`` directory.
|
||||
broadening. A comprehensive multipole data library containing all nuclides in
|
||||
ENDF/B-VII.1 is available on `GitHub
|
||||
<https://github.com/mit-crpg/WMP_Library>`_. 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`.
|
||||
|
||||
--------------------------
|
||||
Multi-Group Cross Sections
|
||||
|
|
|
|||
|
|
@ -149,17 +149,6 @@ the following optional arguments:
|
|||
and processing the data may require as much as 40 GB of additional
|
||||
free disk space.
|
||||
|
||||
.. _scripts_multipole:
|
||||
|
||||
-----------------------------
|
||||
``openmc-get-multipole-data``
|
||||
-----------------------------
|
||||
|
||||
This script downloads and extracts windowed multipole data based on
|
||||
ENDF/B-VII.1. It has the following optional arguments:
|
||||
|
||||
-b, --batch Suppress standard in
|
||||
|
||||
.. _scripts_nndc:
|
||||
|
||||
------------------------
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -60,7 +60,7 @@ extern "C" {
|
|||
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_volume(int32_t index, double* volume);
|
||||
int openmc_material_set_density(int32_t index, double density);
|
||||
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_set_volume(int32_t index, double volume);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ constexpr int VERSION_RELEASE {0};
|
|||
constexpr std::array<int, 3> VERSION {VERSION_MAJOR, VERSION_MINOR, VERSION_RELEASE};
|
||||
|
||||
// HDF5 data format
|
||||
constexpr int HDF5_VERSION[] {1, 0};
|
||||
constexpr int HDF5_VERSION[] {2, 0};
|
||||
|
||||
// Version numbers for binary files
|
||||
constexpr std::array<int, 2> VERSION_PARTICLE_RESTART {2, 0};
|
||||
|
|
|
|||
67
include/openmc/cross_sections.h
Normal file
67
include/openmc/cross_sections.h
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
#ifndef OPENMC_CROSS_SECTIONS_H
|
||||
#define OPENMC_CROSS_SECTIONS_H
|
||||
|
||||
#include "pugixml.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
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<std::string> materials_; //!< Materials contained in library
|
||||
std::string path_; //!< File path to library
|
||||
};
|
||||
|
||||
using LibraryKey = std::pair<Library::Type, std::string>;
|
||||
|
||||
//==============================================================================
|
||||
// Global variable declarations
|
||||
//==============================================================================
|
||||
|
||||
namespace data {
|
||||
|
||||
//!< Data libraries
|
||||
extern std::vector<Library> libraries;
|
||||
|
||||
//! Maps (type, name) to index in libraries
|
||||
extern std::map<LibraryKey, std::size_t> library_map;
|
||||
|
||||
} // namespace data
|
||||
|
||||
//==============================================================================
|
||||
// Non-member functions
|
||||
//==============================================================================
|
||||
|
||||
//! Read cross sections file (either XML or multigroup H5) and populate data
|
||||
//! libraries
|
||||
extern "C" void read_cross_sections_xml();
|
||||
|
||||
//! Read cross_sections.xml and populate data libraries
|
||||
void read_ce_cross_sections_xml();
|
||||
|
||||
} // namespace openmc
|
||||
|
||||
#endif // OPENMC_CROSS_SECTIONS_H
|
||||
|
|
@ -52,7 +52,6 @@ extern "C" bool dagmc; //!< indicator of DAGMC geometry
|
|||
// 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_multipole; //!< directory containing multipole files
|
||||
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;
|
||||
|
|
@ -62,7 +61,7 @@ extern std::string path_statepoint; //!< path to a statepoint file
|
|||
extern "C" int32_t index_entropy_mesh; //!< Index of entropy mesh in global mesh array
|
||||
extern "C" int32_t index_ufs_mesh; //!< Index of UFS mesh in global mesh array
|
||||
extern "C" int32_t index_cmfd_mesh; //!< Index of CMFD mesh in global mesh array
|
||||
|
||||
|
||||
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
|
||||
|
|
@ -77,6 +76,7 @@ extern "C" int n_max_batches; //!< Maximum number of batches
|
|||
extern "C" int res_scat_method; //!< resonance upscattering method
|
||||
extern "C" double res_scat_energy_min; //!< Min energy in [eV] for res. upscattering
|
||||
extern "C" double res_scat_energy_max; //!< Max energy in [eV] for res. upscattering
|
||||
extern std::vector<std::string> res_scat_nuclides; //!< Nuclides using res. upscattering treatment
|
||||
extern "C" int run_mode; //!< Run mode (eigenvalue, fixed src, etc.)
|
||||
extern std::unordered_set<int> sourcepoint_batch; //!< Batches when source should be written
|
||||
extern std::unordered_set<int> statepoint_batch; //!< Batches when state should be written
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
//! \file string_functions.h
|
||||
//! A collection of helper routines for C-strings and STL strings
|
||||
|
||||
#ifndef OPENMC_STRING_FUNCTIONS_H
|
||||
#define OPENMC_STRING_FUNCTIONS_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace openmc {
|
||||
|
||||
std::string& strtrim(std::string& s);
|
||||
|
||||
char* strtrim(char* c_str);
|
||||
|
||||
void to_lower(std::string& str);
|
||||
|
||||
int word_count(std::string const& str);
|
||||
|
||||
} // namespace openmc
|
||||
#endif // STRING_FUNCTIONS_H
|
||||
|
|
@ -1,42 +1,24 @@
|
|||
#ifndef OPENMC_STRING_UTILS_H
|
||||
#define OPENMC_STRING_UTILS_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace openmc {
|
||||
|
||||
inline std::vector<std::string>
|
||||
split(const std::string& in)
|
||||
{
|
||||
std::vector<std::string> out;
|
||||
std::string& strtrim(std::string& s);
|
||||
|
||||
for (int i = 0; i < in.size(); ) {
|
||||
// Increment i until we find a non-whitespace character.
|
||||
if (std::isspace(in[i])) {
|
||||
i++;
|
||||
char* strtrim(char* c_str);
|
||||
|
||||
} else {
|
||||
// Find the next whitespace character at j.
|
||||
int j = i + 1;
|
||||
while (j < in.size() && std::isspace(in[j]) == 0) {j++;}
|
||||
void to_lower(std::string& str);
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
int word_count(std::string const& str);
|
||||
|
||||
return out;
|
||||
}
|
||||
std::vector<std::string> split(const std::string& in);
|
||||
|
||||
inline 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 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
|
||||
|
|
|
|||
|
|
@ -53,11 +53,6 @@ to locate HDF5 format cross section libraries if the user has not specified the
|
|||
Indicates the default path to an HDF5 file that contains multi-group cross
|
||||
section libraries if the user has not specified the <cross_sections> tag in
|
||||
.I materials.xml\fP.
|
||||
.TP
|
||||
.B OPENMC_MULTIPOLE_LIBRARY
|
||||
Indicates the default path to a directory containing windowed multipole data if
|
||||
the user has not specified the <multipole_library> tag in
|
||||
.I materials.xml\fP.
|
||||
.SH LICENSE
|
||||
Copyright \(co 2011-2018 Massachusetts Institute of Technology and OpenMC
|
||||
contributors.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import hashlib
|
||||
import os.path
|
||||
from pathlib import Path
|
||||
from urllib.parse import urlparse
|
||||
|
|
@ -6,13 +7,15 @@ from urllib.request import urlopen
|
|||
_BLOCK_SIZE = 16384
|
||||
|
||||
|
||||
def download(url):
|
||||
def download(url, checksum=None):
|
||||
"""Download file from a URL
|
||||
|
||||
Parameters
|
||||
----------
|
||||
url : str
|
||||
URL from which to download
|
||||
checksum : str or None
|
||||
MD5 checksum to check against
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
|
@ -46,4 +49,13 @@ def download(url):
|
|||
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
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ _dll.openmc_material_get_densities.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]
|
||||
_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 = [
|
||||
|
|
@ -178,16 +178,18 @@ class Material(_FortranObjectWithID):
|
|||
"""
|
||||
_dll.openmc_material_add_nuclide(self._index, name.encode(), density)
|
||||
|
||||
def set_density(self, density):
|
||||
def set_density(self, density, units='atom/b-cm'):
|
||||
"""Set density of a material.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
density : float
|
||||
Density in atom/b-cm
|
||||
Density
|
||||
units : {'atom/b-cm', 'g/cm3'}
|
||||
Units for density
|
||||
|
||||
"""
|
||||
_dll.openmc_material_set_density(self._index, 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
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# Version of HDF5 nuclear data format
|
||||
HDF5_VERSION_MAJOR = 1
|
||||
HDF5_VERSION_MAJOR = 2
|
||||
HDF5_VERSION_MINOR = 0
|
||||
HDF5_VERSION = (HDF5_VERSION_MAJOR, HDF5_VERSION_MINOR)
|
||||
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ def ascii_to_binary(ascii_file, binary_file):
|
|||
"""
|
||||
|
||||
# Open ASCII file
|
||||
ascii = open(ascii_file, 'r')
|
||||
ascii = open(str(ascii_file), 'r')
|
||||
|
||||
# Set default record length
|
||||
record_length = 4096
|
||||
|
|
@ -116,7 +116,7 @@ def ascii_to_binary(ascii_file, binary_file):
|
|||
ascii.close()
|
||||
|
||||
# Open binary file
|
||||
binary = open(binary_file, 'wb')
|
||||
binary = open(str(binary_file), 'wb')
|
||||
|
||||
idx = 0
|
||||
|
||||
|
|
@ -228,8 +228,9 @@ class Library(EqualityMixin):
|
|||
self.tables = []
|
||||
|
||||
# Determine whether file is ASCII or binary
|
||||
filename = str(filename)
|
||||
try:
|
||||
fh = open(str(filename), 'rb')
|
||||
fh = open(filename, 'rb')
|
||||
# Grab 10 lines of the library
|
||||
sb = b''.join([fh.readline() for i in range(10)])
|
||||
|
||||
|
|
|
|||
|
|
@ -348,7 +348,7 @@ def get_evaluations(filename):
|
|||
|
||||
"""
|
||||
evaluations = []
|
||||
with open(filename, 'r') as fh:
|
||||
with open(str(filename), 'r') as fh:
|
||||
while True:
|
||||
pos = fh.tell()
|
||||
line = fh.readline()
|
||||
|
|
|
|||
|
|
@ -279,11 +279,11 @@ class FissionEnergyRelease(EqualityMixin):
|
|||
# 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.reactions:
|
||||
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.reactions:
|
||||
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')]
|
||||
|
|
|
|||
|
|
@ -518,7 +518,7 @@ class Sum(EqualityMixin):
|
|||
"""
|
||||
|
||||
def __init__(self, functions):
|
||||
self.functions = functions
|
||||
self.functions = list(functions)
|
||||
|
||||
def __call__(self, x):
|
||||
return sum(f(x) for f in self.functions)
|
||||
|
|
|
|||
|
|
@ -52,17 +52,13 @@ class DataLibrary(EqualityMixin):
|
|||
Path to the file to be registered.
|
||||
|
||||
"""
|
||||
with h5py.File(filename, 'r') as h5file:
|
||||
# Support pathlib
|
||||
# TODO: Remove when support is Python 3.6+ only
|
||||
filename = str(filename)
|
||||
|
||||
materials = []
|
||||
if 'filetype' in h5file.attrs:
|
||||
filetype = h5file.attrs['filetype'].decode().lstrip('data_')
|
||||
else:
|
||||
filetype = 'neutron'
|
||||
for name in h5file:
|
||||
if name.startswith('c_'):
|
||||
filetype = 'thermal'
|
||||
materials.append(name)
|
||||
with h5py.File(filename, 'r') as h5file:
|
||||
filetype = h5file.attrs['filetype'].decode()[5:]
|
||||
materials = list(h5file)
|
||||
|
||||
library = {'path': filename, 'type': filetype, 'materials': materials}
|
||||
self.libraries.append(library)
|
||||
|
|
@ -84,7 +80,7 @@ class DataLibrary(EqualityMixin):
|
|||
if common_dir == '':
|
||||
common_dir = '.'
|
||||
|
||||
if os.path.relpath(common_dir, os.path.dirname(path)) != '.':
|
||||
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)
|
||||
|
||||
|
|
@ -99,7 +95,7 @@ class DataLibrary(EqualityMixin):
|
|||
|
||||
# Write XML file
|
||||
tree = ET.ElementTree(root)
|
||||
tree.write(path, xml_declaration=True, encoding='utf-8',
|
||||
tree.write(str(path), xml_declaration=True, encoding='utf-8',
|
||||
method='xml')
|
||||
|
||||
@classmethod
|
||||
|
|
@ -131,7 +127,9 @@ class DataLibrary(EqualityMixin):
|
|||
raise ValueError("Either path or OPENMC_CROSS_SECTIONS "
|
||||
"environmental variable must be set")
|
||||
|
||||
check_type('path', path, str)
|
||||
# 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()
|
||||
|
|
|
|||
|
|
@ -333,7 +333,7 @@ class WindowedMultipole(EqualityMixin):
|
|||
if isinstance(group_or_filename, h5py.Group):
|
||||
group = group_or_filename
|
||||
else:
|
||||
h5file = h5py.File(group_or_filename, 'r')
|
||||
h5file = h5py.File(str(group_or_filename), 'r')
|
||||
|
||||
# Make sure version matches
|
||||
if 'version' in h5file.attrs:
|
||||
|
|
@ -515,7 +515,7 @@ class WindowedMultipole(EqualityMixin):
|
|||
"""
|
||||
|
||||
# Open file and write version.
|
||||
with h5py.File(path, mode, libver=libver) as f:
|
||||
with h5py.File(str(path), mode, libver=libver) as f:
|
||||
f.attrs['filetype'] = np.string_('data_wmp')
|
||||
f.attrs['version'] = np.array(WMP_VERSION)
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import sys
|
|||
from collections import OrderedDict
|
||||
from collections.abc import Iterable, Mapping, MutableMapping
|
||||
from io import StringIO
|
||||
from itertools import chain
|
||||
from math import log10
|
||||
from numbers import Integral, Real
|
||||
import os
|
||||
|
|
@ -86,9 +85,6 @@ class IncidentNeutron(EqualityMixin):
|
|||
Resonance parameters
|
||||
resonance_covariance : openmc.data.ResonanceCovariance or None
|
||||
Covariance for resonance parameters
|
||||
redundant_reactions : collections.OrderedDict
|
||||
Contains redundant cross sections, e.g., the total cross section. The keys
|
||||
are the MT values and the values are Reaction objects.
|
||||
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,
|
||||
|
|
@ -113,18 +109,15 @@ class IncidentNeutron(EqualityMixin):
|
|||
self.energy = {}
|
||||
self._fission_energy = None
|
||||
self.reactions = OrderedDict()
|
||||
self.redundant_reactions = OrderedDict()
|
||||
self._urr = {}
|
||||
self._resonances = None
|
||||
|
||||
def __contains__(self, mt):
|
||||
return mt in self.reactions or mt in self.redundant_reactions
|
||||
return mt in self.reactions
|
||||
|
||||
def __getitem__(self, mt):
|
||||
if mt in self.reactions:
|
||||
return self.reactions[mt]
|
||||
elif mt in self.redundant_reactions:
|
||||
return self.redundant_reactions[mt]
|
||||
else:
|
||||
raise KeyError('No reaction with MT={}.'.format(mt))
|
||||
|
||||
|
|
@ -170,10 +163,6 @@ class IncidentNeutron(EqualityMixin):
|
|||
def resonance_covariance(self):
|
||||
return self._resonance_covariance
|
||||
|
||||
@property
|
||||
def redundant_reactions(self):
|
||||
return self._redundant_reactions
|
||||
|
||||
@property
|
||||
def urr(self):
|
||||
return self._urr
|
||||
|
|
@ -237,11 +226,6 @@ class IncidentNeutron(EqualityMixin):
|
|||
res_cov.ResonanceCovariances)
|
||||
self._resonance_covariance = resonance_covariance
|
||||
|
||||
@redundant_reactions.setter
|
||||
def redundant_reactions(self, redundant_reactions):
|
||||
cv.check_type('redundant reactions', redundant_reactions, Mapping)
|
||||
self._redundant_reactions = redundant_reactions
|
||||
|
||||
@urr.setter
|
||||
def urr(self, urr):
|
||||
cv.check_type('probability table dictionary', urr, MutableMapping)
|
||||
|
|
@ -288,7 +272,7 @@ class IncidentNeutron(EqualityMixin):
|
|||
self.energy[strT] = data.energy[strT]
|
||||
|
||||
# Add normal and redundant reactions
|
||||
for mt in chain(data.reactions, data.redundant_reactions):
|
||||
for mt in data.reactions:
|
||||
if mt in self:
|
||||
self[mt].xs[strT] = data[mt].xs[strT]
|
||||
else:
|
||||
|
|
@ -406,24 +390,14 @@ class IncidentNeutron(EqualityMixin):
|
|||
have cross sections provided.
|
||||
|
||||
"""
|
||||
if mt in self.reactions:
|
||||
return [mt]
|
||||
elif mt in SUM_RULES:
|
||||
mts = SUM_RULES[mt]
|
||||
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 []
|
||||
complete = False
|
||||
while not complete:
|
||||
new_mts = []
|
||||
complete = True
|
||||
for i, mt_i in enumerate(mts):
|
||||
if mt_i in self.reactions:
|
||||
new_mts.append(mt_i)
|
||||
elif mt_i in SUM_RULES:
|
||||
new_mts += SUM_RULES[mt_i]
|
||||
complete = False
|
||||
mts = new_mts
|
||||
return mts
|
||||
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.
|
||||
|
|
@ -446,7 +420,7 @@ class IncidentNeutron(EqualityMixin):
|
|||
'originated from an ENDF file.')
|
||||
|
||||
# Open file and write version
|
||||
f = h5py.File(path, mode, libver=libver)
|
||||
f = h5py.File(str(path), mode, libver=libver)
|
||||
f.attrs['filetype'] = np.string_('data_neutron')
|
||||
f.attrs['version'] = np.array(HDF5_VERSION)
|
||||
|
||||
|
|
@ -472,6 +446,15 @@ class IncidentNeutron(EqualityMixin):
|
|||
# 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.
|
||||
if rx.redundant:
|
||||
photon_rx = any(p.particle == 'photon' for p in rx.products)
|
||||
transmutation_rx = (rx.mt in (16, 103, 104, 105, 106, 107))
|
||||
if not (photon_rx or transmutation_rx or rx.mt == 4):
|
||||
continue
|
||||
|
||||
rx_group = rxs_group.create_group('reaction_{:03}'.format(rx.mt))
|
||||
rx.to_hdf5(rx_group)
|
||||
|
||||
|
|
@ -480,12 +463,6 @@ class IncidentNeutron(EqualityMixin):
|
|||
tgroup = g.create_group('total_nu')
|
||||
rx.derived_products[0].to_hdf5(tgroup)
|
||||
|
||||
# Write redundant reaction data only for reactions with photon production
|
||||
for rx in self.redundant_reactions.values():
|
||||
if any(p.particle == 'photon' for p in rx.products):
|
||||
rx_group = rxs_group.create_group('reaction_{:03}'.format(rx.mt))
|
||||
rx.to_hdf5(rx_group)
|
||||
|
||||
# Write unresolved resonance probability tables
|
||||
if self.urr:
|
||||
urr_group = g.create_group('urr')
|
||||
|
|
@ -520,16 +497,12 @@ class IncidentNeutron(EqualityMixin):
|
|||
if isinstance(group_or_filename, h5py.Group):
|
||||
group = group_or_filename
|
||||
else:
|
||||
h5file = h5py.File(group_or_filename, 'r')
|
||||
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))
|
||||
# For now all versions of HDF5 data can be read
|
||||
else:
|
||||
raise IOError(
|
||||
'HDF5 data does not indicate a version. Your installation of '
|
||||
|
|
@ -561,10 +534,7 @@ class IncidentNeutron(EqualityMixin):
|
|||
for name, obj in sorted(rxs_group.items()):
|
||||
if name.startswith('reaction_'):
|
||||
rx = Reaction.from_hdf5(obj, data.energy)
|
||||
if rx.redundant:
|
||||
data.redundant_reactions[rx.mt] = rx
|
||||
else:
|
||||
data.reactions[rx.mt] = rx
|
||||
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:
|
||||
|
|
@ -577,7 +547,8 @@ class IncidentNeutron(EqualityMixin):
|
|||
if mt_sum not in data:
|
||||
rxs = [data[mt] for mt in SUM_RULES[mt_sum] if mt in data]
|
||||
if len(rxs) > 0:
|
||||
data.redundant_reactions[mt_sum] = rx = Reaction(mt_sum)
|
||||
data.reactions[mt_sum] = rx = Reaction(mt_sum)
|
||||
rx.redundant = True
|
||||
if rx.mt == 18 and 'total_nu' in group:
|
||||
tgroup = group['total_nu']
|
||||
rx.derived_products.append(Product.from_hdf5(tgroup))
|
||||
|
|
@ -654,18 +625,21 @@ class IncidentNeutron(EqualityMixin):
|
|||
total = Reaction(1)
|
||||
total.xs[strT] = Tabulated1D(energy, total_xs)
|
||||
total.redundant = True
|
||||
data.redundant_reactions[1] = total
|
||||
data.reactions[1] = total
|
||||
|
||||
if np.count_nonzero(absorption_xs) > 0:
|
||||
absorption = Reaction(27)
|
||||
absorption = Reaction(101)
|
||||
absorption.xs[strT] = Tabulated1D(energy, absorption_xs)
|
||||
absorption.redundant = True
|
||||
data.redundant_reactions[27] = absorption
|
||||
data.reactions[101] = absorption
|
||||
|
||||
# Read each reaction
|
||||
n_reaction = ace.nxs[4] + 1
|
||||
for i in range(n_reaction):
|
||||
rx = Reaction.from_ace(ace, i)
|
||||
# Don't include gas production / damage cross sections
|
||||
if 200 < rx.mt < 219 or rx.mt == 444:
|
||||
continue
|
||||
data.reactions[rx.mt] = rx
|
||||
|
||||
# Some photon production reactions may be assigned to MTs that don't
|
||||
|
|
@ -683,23 +657,39 @@ class IncidentNeutron(EqualityMixin):
|
|||
continue
|
||||
|
||||
# Create redundant reaction with appropriate cross section
|
||||
rx = Reaction(mt)
|
||||
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
|
||||
|
||||
xss = [data.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
|
||||
# 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.products += _get_photon_products_ace(ace, rx)
|
||||
data.redundant_reactions[mt] = rx
|
||||
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
|
||||
|
||||
# Read unresolved resonance probability tables
|
||||
urr = ProbabilityTables.from_ace(ace)
|
||||
|
|
@ -842,3 +832,33 @@ class IncidentNeutron(EqualityMixin):
|
|||
data[2].xs['0K'] = xs
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -146,14 +146,14 @@ def run(commands, tapein, tapeout, input_filename=None, stdout=False,
|
|||
"""
|
||||
|
||||
if input_filename is not None:
|
||||
with open(input_filename, 'w') as f:
|
||||
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(filename, tmpfilename)
|
||||
shutil.copy(str(filename), tmpfilename)
|
||||
|
||||
# Start up NJOY process
|
||||
njoy = Popen([njoy_exec], cwd=tmpdir, stdin=PIPE, stdout=PIPE,
|
||||
|
|
@ -182,7 +182,7 @@ def run(commands, tapein, tapeout, input_filename=None, stdout=False,
|
|||
for tape_num, filename in tapeout.items():
|
||||
tmpfilename = os.path.join(tmpdir, 'tape{}'.format(tape_num))
|
||||
if os.path.isfile(tmpfilename):
|
||||
shutil.move(tmpfilename, filename)
|
||||
shutil.move(tmpfilename, str(filename))
|
||||
|
||||
|
||||
def make_pendf(filename, pendf='pendf', error=0.001, stdout=False):
|
||||
|
|
@ -422,7 +422,7 @@ def make_ace_thermal(filename, filename_thermal, temperatures=None,
|
|||
commands = ""
|
||||
|
||||
nendf, nthermal_endf, npendf = 20, 21, 22
|
||||
tapein = {nendf: filename, nthermal_endf:filename_thermal}
|
||||
tapein = {nendf: filename, nthermal_endf: filename_thermal}
|
||||
tapeout = {}
|
||||
|
||||
# reconr
|
||||
|
|
|
|||
|
|
@ -373,9 +373,6 @@ class IncidentPhoton(EqualityMixin):
|
|||
excitation energy), 's_collision' (collision stopping power in
|
||||
[eV cm\ :sup:`2`/g]), and 's_radiative' (radiative stopping power in
|
||||
[eV cm\ :sup:`2`/g])
|
||||
redundant_reactions : collections.OrderedDict
|
||||
Contains redundant cross sections. The keys are MT values and the values
|
||||
are instances of :class:`PhotonReaction`.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -383,19 +380,16 @@ class IncidentPhoton(EqualityMixin):
|
|||
self.atomic_number = atomic_number
|
||||
self._atomic_relaxation = None
|
||||
self.reactions = OrderedDict()
|
||||
self.redundant_reactions = OrderedDict()
|
||||
self.compton_profiles = {}
|
||||
self.stopping_powers = {}
|
||||
self.bremsstrahlung = {}
|
||||
|
||||
def __contains__(self, mt):
|
||||
return mt in self.reactions or mt in self.redundant_reactions
|
||||
return mt in self.reactions
|
||||
|
||||
def __getitem__(self, mt):
|
||||
if mt in self.reactions:
|
||||
return self.reactions[mt]
|
||||
elif mt in self.redundant_reactions:
|
||||
return self.redundant_reactions[mt]
|
||||
else:
|
||||
raise KeyError('No reaction with MT={}.'.format(mt))
|
||||
|
||||
|
|
@ -668,7 +662,7 @@ class IncidentPhoton(EqualityMixin):
|
|||
|
||||
"""
|
||||
# Open file and write version
|
||||
f = h5py.File(path, mode, libver=libver)
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -278,7 +278,7 @@ class ThermalScattering(EqualityMixin):
|
|||
|
||||
"""
|
||||
# Open file and write version
|
||||
f = h5py.File(path, mode, libver=libver)
|
||||
f = h5py.File(str(path), mode, libver=libver)
|
||||
f.attrs['filetype'] = np.string_('data_thermal')
|
||||
f.attrs['version'] = np.array(HDF5_VERSION)
|
||||
|
||||
|
|
@ -387,7 +387,7 @@ class ThermalScattering(EqualityMixin):
|
|||
if isinstance(group_or_filename, h5py.Group):
|
||||
group = group_or_filename
|
||||
else:
|
||||
h5file = h5py.File(group_or_filename, 'r')
|
||||
h5file = h5py.File(str(group_or_filename), 'r')
|
||||
|
||||
# Make sure version matches
|
||||
if 'version' in h5file.attrs:
|
||||
|
|
|
|||
|
|
@ -989,18 +989,12 @@ class Materials(cv.CheckedList):
|
|||
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.
|
||||
multipole_library : str
|
||||
Indicates the path to a directory containing a windowed multipole
|
||||
cross section library. If it is not set, the
|
||||
:envvar:`OPENMC_MULTIPOLE_LIBRARY` environment variable will be used. A
|
||||
multipole library is optional.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, materials=None):
|
||||
super().__init__(Material, 'materials collection')
|
||||
self._cross_sections = None
|
||||
self._multipole_library = None
|
||||
|
||||
if materials is not None:
|
||||
self += materials
|
||||
|
|
@ -1009,20 +1003,11 @@ class Materials(cv.CheckedList):
|
|||
def cross_sections(self):
|
||||
return self._cross_sections
|
||||
|
||||
@property
|
||||
def multipole_library(self):
|
||||
return self._multipole_library
|
||||
|
||||
@cross_sections.setter
|
||||
def cross_sections(self, cross_sections):
|
||||
cv.check_type('cross sections', cross_sections, str)
|
||||
self._cross_sections = cross_sections
|
||||
|
||||
@multipole_library.setter
|
||||
def multipole_library(self, multipole_library):
|
||||
cv.check_type('cross sections', multipole_library, str)
|
||||
self._multipole_library = multipole_library
|
||||
|
||||
def append(self, material):
|
||||
"""Append material to collection
|
||||
|
||||
|
|
@ -1060,11 +1045,6 @@ class Materials(cv.CheckedList):
|
|||
element = ET.SubElement(root_element, "cross_sections")
|
||||
element.text = str(self._cross_sections)
|
||||
|
||||
def _create_multipole_library_subelement(self, root_element):
|
||||
if self._multipole_library is not None:
|
||||
element = ET.SubElement(root_element, "multipole_library")
|
||||
element.text = str(self._multipole_library)
|
||||
|
||||
def export_to_xml(self, path='materials.xml'):
|
||||
"""Export material collection to an XML file.
|
||||
|
||||
|
|
@ -1077,7 +1057,6 @@ class Materials(cv.CheckedList):
|
|||
|
||||
root_element = ET.Element("materials")
|
||||
self._create_cross_sections_subelement(root_element)
|
||||
self._create_multipole_library_subelement(root_element)
|
||||
self._create_material_subelements(root_element)
|
||||
|
||||
# Clean the indentation in the file to be user-readable
|
||||
|
|
@ -1114,8 +1093,5 @@ class Materials(cv.CheckedList):
|
|||
xs = tree.find('cross_sections')
|
||||
if xs is not None:
|
||||
materials.cross_sections = xs.text
|
||||
mpl = tree.find('multipole_library')
|
||||
if mpl is not None:
|
||||
materials.multipole_library = mpl.text
|
||||
|
||||
return materials
|
||||
|
|
|
|||
|
|
@ -180,7 +180,6 @@ class Settings(object):
|
|||
self._confidence_intervals = None
|
||||
self._cross_sections = None
|
||||
self._electron_treatment = None
|
||||
self._multipole_library = None
|
||||
self._photon_transport = None
|
||||
self._ptables = None
|
||||
self._run_cmfd = None
|
||||
|
|
|
|||
99
scripts/openmc-convert-lib80x-data
Executable file
99
scripts/openmc-convert-lib80x-data
Executable file
|
|
@ -0,0 +1,99 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
from collections import defaultdict
|
||||
import glob
|
||||
import os
|
||||
|
||||
import openmc.data
|
||||
|
||||
|
||||
description = """
|
||||
Convert ENDF/B-VIII.0 ACE data from LANL into an HDF5 library
|
||||
that can be used by OpenMC. This assumes that you have a directory containing
|
||||
subdirectories 'Lib80x' and 'ENDF80SaB'.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
class CustomFormatter(argparse.ArgumentDefaultsHelpFormatter,
|
||||
argparse.RawDescriptionHelpFormatter):
|
||||
pass
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description=description,
|
||||
formatter_class=CustomFormatter
|
||||
)
|
||||
parser.add_argument('-o', '--output_dir', default='lib80x_hdf5',
|
||||
help='Directory to create new library in')
|
||||
parser.add_argument('--libver', choices=['earliest', 'latest'],
|
||||
default='earliest', help="Output HDF5 versioning. Use "
|
||||
"'earliest' for backwards compatibility or 'latest' for "
|
||||
"performance")
|
||||
parser.add_argument('--datadir', help='Directory containing Lib80x and ENDF80SaB',
|
||||
default=os.curdir)
|
||||
args = parser.parse_args()
|
||||
assert os.path.isdir(args.datadir)
|
||||
|
||||
# Get a list of all ACE files
|
||||
lib80x = glob.glob(os.path.join(args.datadir, 'Lib80x', '**', '*.80?nc'), recursive=True)
|
||||
lib80sab = glob.glob(os.path.join(args.datadir, 'ENDF80SaB', '**', '*.??t'), recursive=True)
|
||||
|
||||
# Find and fix B10 ACE files
|
||||
b10files = glob.glob(os.path.join(args.datadir, 'Lib80x', '**', '5010.80?nc'), recursive=True)
|
||||
nxs1_position = 523
|
||||
for filename in b10files:
|
||||
with open(filename, 'r+') as fh:
|
||||
# Read NXS(1)
|
||||
fh.seek(nxs1_position)
|
||||
nxs1 = int(fh.read(5))
|
||||
|
||||
# Increase length to match actual length of XSS, but make sure this
|
||||
# isn't done twice by checking the current length
|
||||
if nxs1 < 86870:
|
||||
fh.seek(nxs1_position)
|
||||
fh.write(str(nxs1 + 53))
|
||||
|
||||
# Group together tables for the same nuclide
|
||||
suffixes = defaultdict(list)
|
||||
for filename in sorted(lib80x + lib80sab):
|
||||
dirname, basename = os.path.split(filename)
|
||||
zaid, xs = basename.split('.')
|
||||
suffixes[os.path.join(dirname, zaid)].append(xs)
|
||||
|
||||
# Create output directory if it doesn't exist
|
||||
if not os.path.isdir(args.output_dir):
|
||||
os.mkdir(args.output_dir)
|
||||
|
||||
library = openmc.data.DataLibrary()
|
||||
|
||||
for basename, xs_list in sorted(suffixes.items()):
|
||||
# Convert first temperature for the table
|
||||
filename = '.'.join((basename, xs_list[0]))
|
||||
print('Converting: ' + filename)
|
||||
if filename.endswith('t'):
|
||||
data = openmc.data.ThermalScattering.from_ace(filename)
|
||||
else:
|
||||
data = openmc.data.IncidentNeutron.from_ace(filename, 'mcnp')
|
||||
|
||||
# For each higher temperature, add cross sections to the existing table
|
||||
for xs in xs_list[1:]:
|
||||
filename = '.'.join((basename, xs))
|
||||
print('Adding: ' + filename)
|
||||
if filename.endswith('t'):
|
||||
data.add_temperature_from_ace(filename)
|
||||
else:
|
||||
data.add_temperature_from_ace(filename, 'mcnp')
|
||||
|
||||
# Export HDF5 file
|
||||
h5_file = os.path.join(args.output_dir, data.name + '.h5')
|
||||
print('Writing {}...'.format(h5_file))
|
||||
data.export_to_hdf5(h5_file, 'w', libver=args.libver)
|
||||
|
||||
# Register with library
|
||||
library.register_file(h5_file)
|
||||
|
||||
# Write cross_sections.xml
|
||||
libpath = os.path.join(args.output_dir, 'cross_sections.xml')
|
||||
library.export_to_xml(libpath)
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tarfile
|
||||
import glob
|
||||
import hashlib
|
||||
import argparse
|
||||
from urllib.request import urlopen
|
||||
|
||||
|
||||
description = """
|
||||
Download and extract windowed multipole data based on ENDF/B-VII.1.
|
||||
|
||||
"""
|
||||
|
||||
class CustomFormatter(argparse.ArgumentDefaultsHelpFormatter,
|
||||
argparse.RawDescriptionHelpFormatter):
|
||||
pass
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description=description,
|
||||
formatter_class=CustomFormatter
|
||||
)
|
||||
parser.add_argument('-b', '--batch', action='store_true',
|
||||
help='supresses standard in')
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
baseUrl = 'https://github.com/mit-crpg/WMP_Library/releases/download/v1.1/'
|
||||
files = ['WMP_Library_v1.1.tar.gz']
|
||||
checksums = ['8523895928dd6ba63fba803e3a45d4f3']
|
||||
block_size = 16384
|
||||
|
||||
# ==============================================================================
|
||||
# DOWNLOAD FILES FROM GITHUB REPO
|
||||
|
||||
filesComplete = []
|
||||
for f in files:
|
||||
# Establish connection to URL
|
||||
url = baseUrl + f
|
||||
req = urlopen(url)
|
||||
|
||||
# Get file size from header
|
||||
if sys.version_info[0] < 3:
|
||||
file_size = int(req.info().getheaders('Content-Length')[0])
|
||||
else:
|
||||
file_size = req.length
|
||||
downloaded = 0
|
||||
|
||||
# Remove GitHub junk from the file name.
|
||||
fname = f[:-9] if f.endswith('?raw=true') else f
|
||||
|
||||
# Check if file already downloaded
|
||||
if os.path.exists(fname):
|
||||
if os.path.getsize(fname) == file_size:
|
||||
print('Skipping ' + fname)
|
||||
filesComplete.append(fname)
|
||||
continue
|
||||
else:
|
||||
overwrite = input('Overwrite {0}? ([y]/n) '.format(fname))
|
||||
if overwrite.lower().startswith('n'):
|
||||
continue
|
||||
|
||||
# Copy file to disk
|
||||
print('Downloading {0}... '.format(f), end='')
|
||||
with open(fname, '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('')
|
||||
filesComplete.append(fname)
|
||||
|
||||
# ==============================================================================
|
||||
# VERIFY MD5 CHECKSUMS
|
||||
|
||||
print('Verifying MD5 checksums...')
|
||||
for f, checksum in zip(files, checksums):
|
||||
fname = f[:-9] if f.endswith('?raw=true') else f
|
||||
downloadsum = hashlib.md5(open(fname, '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(f))
|
||||
|
||||
# ==============================================================================
|
||||
# EXTRACT FILES FROM TGZ
|
||||
|
||||
for f in files:
|
||||
fname = f[:-9] if f.endswith('?raw=true') else f
|
||||
if fname not in filesComplete:
|
||||
continue
|
||||
|
||||
# Extract files
|
||||
with tarfile.open(fname, 'r') as tgz:
|
||||
print('Extracting {0}...'.format(fname))
|
||||
tgz.extractall(path='')
|
||||
|
||||
# ==============================================================================
|
||||
# PROMPT USER TO DELETE .TAR.GZ FILES
|
||||
|
||||
# Ask user to delete
|
||||
if not args.batch:
|
||||
response = input('Delete *.tar.gz files? ([y]/n) ')
|
||||
else:
|
||||
response = 'y'
|
||||
|
||||
# Delete files if requested
|
||||
if not response or response.lower().startswith('y'):
|
||||
for f in files:
|
||||
if os.path.exists(f):
|
||||
print('Removing {0}...'.format(f))
|
||||
os.remove(f)
|
||||
164
scripts/openmc-make-test-data
Executable file
164
scripts/openmc-make-test-data
Executable file
|
|
@ -0,0 +1,164 @@
|
|||
#!/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))
|
||||
|
|
@ -79,6 +79,9 @@ contains
|
|||
|
||||
subroutine free_memory_mesh() bind(C)
|
||||
end subroutine free_memory_mesh
|
||||
|
||||
subroutine free_memory_settings() bind(C)
|
||||
end subroutine free_memory_settings
|
||||
end interface
|
||||
|
||||
call free_memory_geometry()
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ module constants
|
|||
VERSION(3) = [VERSION_MAJOR, VERSION_MINOR, VERSION_RELEASE]
|
||||
|
||||
! HDF5 data format
|
||||
integer, parameter :: HDF5_VERSION(2) = [1, 0]
|
||||
integer, parameter :: HDF5_VERSION(2) = [2, 0]
|
||||
|
||||
! WMP data format
|
||||
integer, parameter :: WMP_VERSION(2) = [1, 1]
|
||||
|
|
@ -238,7 +238,8 @@ module constants
|
|||
LIBRARY_NEUTRON = 1, &
|
||||
LIBRARY_THERMAL = 2, &
|
||||
LIBRARY_PHOTON = 3, &
|
||||
LIBRARY_MULTIGROUP = 4
|
||||
LIBRARY_MULTIGROUP = 4, &
|
||||
LIBRARY_WMP = 5
|
||||
|
||||
! Probability table parameters
|
||||
integer, parameter :: &
|
||||
|
|
|
|||
226
src/cross_sections.cpp
Normal file
226
src/cross_sections.cpp
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
#include "openmc/cross_sections.h"
|
||||
|
||||
#include "openmc/constants.h"
|
||||
#include "openmc/container_util.h"
|
||||
#include "openmc/error.h"
|
||||
#include "openmc/file_utils.h"
|
||||
#include "openmc/settings.h"
|
||||
#include "openmc/string_utils.h"
|
||||
#include "openmc/xml_interface.h"
|
||||
|
||||
#include "pugixml.hpp"
|
||||
|
||||
#include <cstdlib> // for getenv
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
// Global variable declarations
|
||||
//==============================================================================
|
||||
|
||||
namespace data {
|
||||
|
||||
std::vector<Library> libraries;
|
||||
std::map<LibraryKey, std::size_t> 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<std::string>(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
|
||||
//==============================================================================
|
||||
|
||||
extern "C" void read_mg_cross_sections_header();
|
||||
|
||||
void read_cross_sections_xml()
|
||||
{
|
||||
// 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
|
||||
pugi::xml_document doc;
|
||||
doc.load_file(filename.c_str());
|
||||
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_) {
|
||||
std::string lower_name = name;
|
||||
to_lower(lower_name);
|
||||
LibraryKey key {lib.type_, lower_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) {
|
||||
std::string lower_name = name;
|
||||
to_lower(lower_name);
|
||||
LibraryKey key {Library::Type::neutron, lower_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_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("/");
|
||||
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.");
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// Fortran compatibility functions
|
||||
//==============================================================================
|
||||
|
||||
extern "C" void library_clear() {
|
||||
data::libraries.clear();
|
||||
data::library_map.clear();
|
||||
}
|
||||
|
||||
extern "C" const char* library_path(int type, const char* name) {
|
||||
auto lib_type = static_cast<Library::Type>(type);
|
||||
LibraryKey key {lib_type, name};
|
||||
if (data::library_map.find(key) == data::library_map.end()) {
|
||||
return nullptr;
|
||||
} else {
|
||||
auto idx = data::library_map[key];
|
||||
return data::libraries[idx].path_.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" bool library_present(int type, const char* name) {
|
||||
auto lib_type = static_cast<Library::Type>(type);
|
||||
LibraryKey key {lib_type, name};
|
||||
return data::library_map.find(key) != data::library_map.end();
|
||||
}
|
||||
|
||||
} // namespace openmc
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
#include "openmc/dagmc.h"
|
||||
#include "openmc/error.h"
|
||||
#include "openmc/string_functions.h"
|
||||
#include "openmc/string_utils.h"
|
||||
#include "openmc/settings.h"
|
||||
#include "openmc/geometry.h"
|
||||
|
||||
|
|
|
|||
22
src/endf.F90
22
src/endf.F90
|
|
@ -229,7 +229,7 @@ contains
|
|||
integer, intent(in) :: MT
|
||||
logical :: dis
|
||||
|
||||
if (MT >= N_GAMMA .and. MT <= N_DA) then
|
||||
if (MT >= N_DISAPPEAR .and. MT <= N_DA) then
|
||||
dis = .true.
|
||||
elseif (MT >= N_P0 .and. MT <= N_AC) then
|
||||
dis = .true.
|
||||
|
|
@ -242,25 +242,27 @@ contains
|
|||
end function is_disappearance
|
||||
|
||||
!===============================================================================
|
||||
! IS_SCATTER determines if a given MT number is that of a scattering event
|
||||
! IS_INELASTIC_SCATTER determines if a given MT number is that of an inelastic
|
||||
! scattering event
|
||||
!===============================================================================
|
||||
|
||||
function is_scatter(MT) result(scatter_event)
|
||||
function is_inelastic_scatter(MT) result(retval)
|
||||
|
||||
integer, intent(in) :: MT
|
||||
logical :: scatter_event
|
||||
logical :: retval
|
||||
|
||||
if (MT < 100) then
|
||||
if (MT == N_FISSION .or. MT == N_F .or. MT == N_NF .or. MT == N_2NF &
|
||||
.or. MT == N_3NF) then
|
||||
scatter_event = .false.
|
||||
if (is_fission(MT)) then
|
||||
retval = .false.
|
||||
else
|
||||
scatter_event = .true.
|
||||
retval = (MT >= MISC .and. MT /= 27)
|
||||
end if
|
||||
elseif (MT <= 200) then
|
||||
retval = (.not. is_disappearance(MT))
|
||||
else
|
||||
scatter_event = .false.
|
||||
retval = .false.
|
||||
end if
|
||||
|
||||
end function is_scatter
|
||||
end function
|
||||
|
||||
end module endf
|
||||
|
|
|
|||
|
|
@ -362,7 +362,7 @@ member_names(hid_t group_id, H5O_type_t type)
|
|||
char buffer[size];
|
||||
H5Lget_name_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i,
|
||||
buffer, size, H5P_DEFAULT);
|
||||
names.emplace_back(&buffer[0], size);
|
||||
names.emplace_back(&buffer[0]);
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,23 +8,23 @@ module initialize
|
|||
implicit none
|
||||
|
||||
interface
|
||||
function openmc_path_input() result(ptr) bind(C)
|
||||
function path_input_c() result(ptr) bind(C)
|
||||
import C_PTR
|
||||
type(C_PTR) :: ptr
|
||||
end function
|
||||
function openmc_path_output() result(ptr) bind(C)
|
||||
function path_output_c() result(ptr) bind(C)
|
||||
import C_PTR
|
||||
type(C_PTR) :: ptr
|
||||
end function
|
||||
function openmc_path_particle_restart() result(ptr) bind(C)
|
||||
function path_particle_restart_c() result(ptr) bind(C)
|
||||
import C_PTR
|
||||
type(C_PTR) :: ptr
|
||||
end function
|
||||
function openmc_path_statepoint() result(ptr) bind(C)
|
||||
function path_statepoint_c() result(ptr) bind(C)
|
||||
import C_PTR
|
||||
type(C_PTR) :: ptr
|
||||
end function
|
||||
function openmc_path_sourcepoint() result(ptr) bind(C)
|
||||
function path_sourcepoint_c() result(ptr) bind(C)
|
||||
import C_PTR
|
||||
type(C_PTR) :: ptr
|
||||
end function
|
||||
|
|
@ -49,22 +49,22 @@ contains
|
|||
end function is_null
|
||||
end interface
|
||||
|
||||
if (.not. is_null(openmc_path_input())) then
|
||||
call c_f_pointer(openmc_path_input(), string, [255])
|
||||
if (.not. is_null(path_input_c())) then
|
||||
call c_f_pointer(path_input_c(), string, [255])
|
||||
path_input = to_f_string(string)
|
||||
else
|
||||
path_input = ''
|
||||
end if
|
||||
if (.not. is_null(openmc_path_statepoint())) then
|
||||
call c_f_pointer(openmc_path_statepoint(), string, [255])
|
||||
if (.not. is_null(path_statepoint_c())) then
|
||||
call c_f_pointer(path_statepoint_c(), string, [255])
|
||||
path_state_point = to_f_string(string)
|
||||
end if
|
||||
if (.not. is_null(openmc_path_sourcepoint())) then
|
||||
call c_f_pointer(openmc_path_sourcepoint(), string, [255])
|
||||
if (.not. is_null(path_sourcepoint_c())) then
|
||||
call c_f_pointer(path_sourcepoint_c(), string, [255])
|
||||
path_source_point = to_f_string(string)
|
||||
end if
|
||||
if (.not. is_null(openmc_path_particle_restart())) then
|
||||
call c_f_pointer(openmc_path_particle_restart(), string, [255])
|
||||
if (.not. is_null(path_particle_restart_c())) then
|
||||
call c_f_pointer(path_particle_restart_c(), string, [255])
|
||||
path_particle_restart = to_f_string(string)
|
||||
end if
|
||||
end subroutine read_command_line
|
||||
|
|
|
|||
|
|
@ -72,6 +72,9 @@ module input_xml
|
|||
type(C_PTR) :: node_ptr
|
||||
end subroutine read_cells
|
||||
|
||||
subroutine read_cross_sections_xml() bind(C)
|
||||
end subroutine
|
||||
|
||||
subroutine read_lattices(node_ptr) bind(C)
|
||||
import C_PTR
|
||||
type(C_PTR) :: node_ptr
|
||||
|
|
@ -123,15 +126,14 @@ contains
|
|||
|
||||
type(VectorReal), allocatable :: nuc_temps(:) ! List of T to read for each nuclide
|
||||
type(VectorReal), allocatable :: sab_temps(:) ! List of T to read for each S(a,b)
|
||||
real(8), allocatable :: material_temps(:)
|
||||
|
||||
call read_settings_xml()
|
||||
call read_cross_sections_xml()
|
||||
call read_materials_xml(material_temps)
|
||||
call read_materials_xml()
|
||||
call read_geometry_xml()
|
||||
|
||||
! Set up neighbor lists, convert user IDs -> indices, assign temperatures
|
||||
call finalize_geometry(material_temps, nuc_temps, sab_temps)
|
||||
call finalize_geometry(nuc_temps, sab_temps)
|
||||
|
||||
if (run_mode /= MODE_PLOTTING) then
|
||||
call time_read_xs % start()
|
||||
|
|
@ -172,8 +174,7 @@ contains
|
|||
|
||||
end subroutine read_input_xml
|
||||
|
||||
subroutine finalize_geometry(material_temps, nuc_temps, sab_temps)
|
||||
real(8), intent(in) :: material_temps(:)
|
||||
subroutine finalize_geometry(nuc_temps, sab_temps)
|
||||
type(VectorReal), allocatable, intent(out) :: nuc_temps(:)
|
||||
type(VectorReal), optional, allocatable, intent(out) :: sab_temps(:)
|
||||
|
||||
|
|
@ -215,27 +216,12 @@ contains
|
|||
integer :: i
|
||||
integer :: n
|
||||
type(XMLNode) :: root
|
||||
type(XMLNode) :: node_res_scat
|
||||
type(XMLNode) :: node_vol
|
||||
type(XMLNode), allocatable :: node_vol_list(:)
|
||||
|
||||
! Get proper XMLNode type given pointer
|
||||
root % ptr = root_ptr
|
||||
|
||||
! Resonance scattering parameters
|
||||
if (check_for_node(root, "resonance_scattering")) then
|
||||
node_res_scat = root % child("resonance_scattering")
|
||||
|
||||
! Get nuclides that resonance scattering should be applied to
|
||||
if (check_for_node(node_res_scat, "nuclides")) then
|
||||
n = node_word_count(node_res_scat, "nuclides")
|
||||
allocate(res_scat_nuclides(n))
|
||||
if (n > 0) then
|
||||
call get_node_array(node_res_scat, "nuclides", res_scat_nuclides)
|
||||
end if
|
||||
end if
|
||||
end if
|
||||
|
||||
call get_node_list(root, "volume_calc", node_vol_list)
|
||||
n = size(node_vol_list)
|
||||
allocate(volume_calcs(n))
|
||||
|
|
@ -547,128 +533,12 @@ contains
|
|||
end do
|
||||
end subroutine allocate_cells
|
||||
|
||||
!===============================================================================
|
||||
! READ_MATERIAL_XML reads data from a materials.xml file and parses it, checking
|
||||
! for errors and placing properly-formatted data in the right data structures
|
||||
!===============================================================================
|
||||
|
||||
subroutine read_cross_sections_xml()
|
||||
integer :: i, j
|
||||
logical :: file_exists
|
||||
character(MAX_FILE_LEN) :: env_variable
|
||||
character(MAX_LINE_LEN) :: filename
|
||||
type(XMLDocument) :: doc
|
||||
type(XMLNode) :: root
|
||||
|
||||
! Check if materials.xml exists
|
||||
filename = trim(path_input) // "materials.xml"
|
||||
inquire(FILE=filename, EXIST=file_exists)
|
||||
if (.not. file_exists) then
|
||||
call fatal_error("Material XML file '" // trim(filename) // "' does not &
|
||||
&exist!")
|
||||
end if
|
||||
|
||||
! Parse materials.xml file
|
||||
call doc % load_file(filename)
|
||||
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 (.not. check_for_node(root, "cross_sections")) then
|
||||
! No cross_sections.xml file specified in settings.xml, check
|
||||
! environment variable
|
||||
if (run_CE) then
|
||||
call get_environment_variable("OPENMC_CROSS_SECTIONS", env_variable)
|
||||
if (len_trim(env_variable) == 0) then
|
||||
call get_environment_variable("CROSS_SECTIONS", env_variable)
|
||||
! FIXME: When deprecated option of setting the cross sections in
|
||||
! settings.xml is removed, remove ".and. path_cross_sections == ''"
|
||||
if (len_trim(env_variable) == 0 .and. path_cross_sections == '') then
|
||||
call fatal_error("No cross_sections.xml file was specified in &
|
||||
&materials.xml, settings.xml, or in the OPENMC_CROSS_SECTIONS&
|
||||
& environment variable. OpenMC needs such a file to identify &
|
||||
&where to find ACE cross section libraries. Please consult the&
|
||||
& user's guide at http://openmc.readthedocs.io for &
|
||||
&information on how to set up ACE cross section libraries.")
|
||||
else
|
||||
call warning("The CROSS_SECTIONS environment variable is &
|
||||
&deprecated. Please update your environment to use &
|
||||
&OPENMC_CROSS_SECTIONS instead.")
|
||||
end if
|
||||
end if
|
||||
path_cross_sections = trim(env_variable)
|
||||
else
|
||||
call get_environment_variable("OPENMC_MG_CROSS_SECTIONS", env_variable)
|
||||
! FIXME: When deprecated option of setting the mg cross sections in
|
||||
! settings.xml is removed, remove ".and. path_cross_sections == ''"
|
||||
if (len_trim(env_variable) == 0 .and. path_cross_sections == '') then
|
||||
call 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.")
|
||||
else if (len_trim(env_variable) /= 0) then
|
||||
path_cross_sections = trim(env_variable)
|
||||
end if
|
||||
end if
|
||||
else
|
||||
call get_node_value(root, "cross_sections", path_cross_sections)
|
||||
end if
|
||||
|
||||
! Find the windowed multipole library
|
||||
if (run_mode /= MODE_PLOTTING) then
|
||||
if (.not. check_for_node(root, "multipole_library")) then
|
||||
! No library location specified in materials.xml, check
|
||||
! environment variable
|
||||
call get_environment_variable("OPENMC_MULTIPOLE_LIBRARY", env_variable)
|
||||
path_multipole = trim(env_variable)
|
||||
else
|
||||
call get_node_value(root, "multipole_library", path_multipole)
|
||||
end if
|
||||
if (.not. ends_with(path_multipole, "/")) &
|
||||
path_multipole = trim(path_multipole) // "/"
|
||||
end if
|
||||
|
||||
! Close materials XML file
|
||||
call doc % clear()
|
||||
|
||||
! Now that the cross_sections.xml or mgxs.h5 has been located, read it in
|
||||
if (run_CE) then
|
||||
call read_ce_cross_sections_xml()
|
||||
else
|
||||
call read_mg_cross_sections_header()
|
||||
end if
|
||||
|
||||
! Creating dictionary that maps the name of the material to the entry
|
||||
do i = 1, size(libraries)
|
||||
do j = 1, size(libraries(i) % materials)
|
||||
call library_dict % set(to_lower(libraries(i) % materials(j)), i)
|
||||
end do
|
||||
end do
|
||||
|
||||
! Check that 0K nuclides are listed in the cross_sections.xml file
|
||||
if (allocated(res_scat_nuclides)) then
|
||||
do i = 1, size(res_scat_nuclides)
|
||||
if (.not. library_dict % has(to_lower(res_scat_nuclides(i)))) then
|
||||
call fatal_error("Could not find resonant scatterer " &
|
||||
// trim(res_scat_nuclides(i)) // " in cross_sections.xml file!")
|
||||
end if
|
||||
end do
|
||||
end if
|
||||
|
||||
end subroutine read_cross_sections_xml
|
||||
|
||||
subroutine read_materials_xml(material_temps)
|
||||
real(8), allocatable, intent(out) :: material_temps(:)
|
||||
|
||||
subroutine read_materials_xml()
|
||||
integer :: i ! loop index for materials
|
||||
integer :: j ! loop index for nuclides
|
||||
integer :: k ! loop index
|
||||
integer :: n ! number of nuclides
|
||||
integer :: n_sab ! number of sab tables for a material
|
||||
integer :: i_library ! index in libraries array
|
||||
integer :: index_nuclide ! index in nuclides
|
||||
integer :: index_element ! index in elements
|
||||
integer :: index_sab ! index in sab_tables
|
||||
|
|
@ -720,7 +590,6 @@ contains
|
|||
! Allocate materials array
|
||||
n_materials = size(node_mat_list)
|
||||
allocate(materials(n_materials))
|
||||
allocate(material_temps(n_materials))
|
||||
|
||||
! Initialize count for number of nuclides/S(a,b) tables
|
||||
index_nuclide = 0
|
||||
|
|
@ -745,13 +614,6 @@ contains
|
|||
call get_node_value(node_mat, "name", mat % name)
|
||||
end if
|
||||
|
||||
! Get material default temperature
|
||||
if (check_for_node(node_mat, "temperature")) then
|
||||
call get_node_value(node_mat, "temperature", material_temps(i))
|
||||
else
|
||||
material_temps(i) = -1.0
|
||||
end if
|
||||
|
||||
! Get pointer to density element
|
||||
if (check_for_node(node_mat, "density")) then
|
||||
node_dens = node_mat % child("density")
|
||||
|
|
@ -940,19 +802,10 @@ contains
|
|||
ALL_NUCLIDES: do j = 1, mat % n_nuclides
|
||||
! Check that this nuclide is listed in the cross_sections.xml file
|
||||
name = trim(names % data(j))
|
||||
if (.not. library_dict % has(to_lower(name))) then
|
||||
if (.not. library_present(LIBRARY_NEUTRON, (to_lower(name)))) then
|
||||
call fatal_error("Could not find nuclide " // trim(name) &
|
||||
// " in cross_sections data file!")
|
||||
end if
|
||||
i_library = library_dict % get(to_lower(name))
|
||||
|
||||
if (run_CE) then
|
||||
! Check to make sure cross-section is continuous energy neutron table
|
||||
if (libraries(i_library) % type /= LIBRARY_NEUTRON) then
|
||||
call fatal_error("Cross-section table " // trim(name) &
|
||||
// " is not a continuous-energy neutron table.")
|
||||
end if
|
||||
end if
|
||||
|
||||
! If this nuclide hasn't been encountered yet, we need to add its name
|
||||
! and alias to the nuclide_dict
|
||||
|
|
@ -971,7 +824,7 @@ contains
|
|||
element = name(1:scan(name, '0123456789') - 1)
|
||||
|
||||
! Make sure photon cross section data is available
|
||||
if (.not. library_dict % has(to_lower(element))) then
|
||||
if (.not. library_present(LIBRARY_PHOTON, to_lower(element))) then
|
||||
call fatal_error("Could not find element " // trim(element) &
|
||||
// " in cross_sections data file!")
|
||||
end if
|
||||
|
|
@ -1065,23 +918,11 @@ contains
|
|||
end if
|
||||
|
||||
! Check that this nuclide is listed in the cross_sections.xml file
|
||||
if (.not. library_dict % has(to_lower(name))) then
|
||||
if (.not. library_present(LIBRARY_THERMAL, to_lower(name))) then
|
||||
call fatal_error("Could not find S(a,b) table " // trim(name) &
|
||||
// " in cross_sections.xml file!")
|
||||
end if
|
||||
|
||||
! Find index in xs_listing and set the name and alias according to the
|
||||
! listing
|
||||
i_library = library_dict % get(to_lower(name))
|
||||
|
||||
if (run_CE) then
|
||||
! Check to make sure cross-section is continuous energy neutron table
|
||||
if (libraries(i_library) % type /= LIBRARY_THERMAL) then
|
||||
call fatal_error("Cross-section table " // trim(name) &
|
||||
// " is not a S(a,b) table.")
|
||||
end if
|
||||
end if
|
||||
|
||||
! If this S(a,b) table hasn't been encountered yet, we need to add its
|
||||
! name and alias to the sab_dict
|
||||
if (.not. sab_dict % has(to_lower(name))) then
|
||||
|
|
@ -2064,130 +1905,27 @@ contains
|
|||
|
||||
end subroutine read_plots_xml
|
||||
|
||||
!===============================================================================
|
||||
! READ_*_CROSS_SECTIONS_XML reads information from a cross_sections.xml file. This
|
||||
! file contains a listing of the CE and MG cross sections that may be used.
|
||||
!===============================================================================
|
||||
|
||||
subroutine read_ce_cross_sections_xml()
|
||||
subroutine read_mg_cross_sections_header() bind(C)
|
||||
integer :: i ! loop index
|
||||
integer :: n
|
||||
integer :: n_libraries
|
||||
logical :: file_exists ! does cross_sections.xml exist?
|
||||
character(MAX_WORD_LEN) :: directory ! directory with cross sections
|
||||
character(MAX_WORD_LEN) :: words(MAX_WORDS)
|
||||
character(10000) :: temp_str
|
||||
type(XMLDocument) :: doc
|
||||
type(XMLNode) :: root
|
||||
type(XMLNode) :: node_library
|
||||
type(XMLNode), allocatable :: node_library_list(:)
|
||||
|
||||
! Check if cross_sections.xml exists
|
||||
inquire(FILE=path_cross_sections, EXIST=file_exists)
|
||||
if (.not. file_exists) then
|
||||
! Could not find cross_sections.xml file
|
||||
call fatal_error("Cross sections XML file '" &
|
||||
// trim(path_cross_sections) // "' does not exist!")
|
||||
end if
|
||||
|
||||
call write_message("Reading cross sections XML file...", 5)
|
||||
|
||||
! Parse cross_sections.xml file
|
||||
call doc % load_file(path_cross_sections)
|
||||
root = doc % document_element()
|
||||
|
||||
if (check_for_node(root, "directory")) then
|
||||
! Copy directory information if present
|
||||
call get_node_value(root, "directory", directory)
|
||||
else
|
||||
! If no directory is listed in cross_sections.xml, by default select the
|
||||
! directory in which the cross_sections.xml file resides
|
||||
i = index(path_cross_sections, "/", BACK=.true.)
|
||||
directory = path_cross_sections(1:i)
|
||||
end if
|
||||
|
||||
! Get node list of all <library>
|
||||
call get_node_list(root, "library", node_library_list)
|
||||
n_libraries = size(node_library_list)
|
||||
|
||||
! Allocate xs_listings array
|
||||
if (n_libraries == 0) then
|
||||
call fatal_error("No cross section libraries present in cross_sections.xml &
|
||||
&file!")
|
||||
else
|
||||
allocate(libraries(n_libraries))
|
||||
end if
|
||||
|
||||
do i = 1, n_libraries
|
||||
! Get pointer to ace table XML node
|
||||
node_library = node_library_list(i)
|
||||
|
||||
! Get list of materials
|
||||
if (check_for_node(node_library, "materials")) then
|
||||
call get_node_value(node_library, "materials", temp_str)
|
||||
call split_string(temp_str, words, n)
|
||||
allocate(libraries(i) % materials(n))
|
||||
libraries(i) % materials(:) = words(1:n)
|
||||
end if
|
||||
|
||||
! Get type of library
|
||||
if (check_for_node(node_library, "type")) then
|
||||
call get_node_value(node_library, "type", temp_str)
|
||||
select case(to_lower(temp_str))
|
||||
case ('neutron')
|
||||
libraries(i) % type = LIBRARY_NEUTRON
|
||||
case ('thermal')
|
||||
libraries(i) % type = LIBRARY_THERMAL
|
||||
case ('photon')
|
||||
libraries(i) % type = LIBRARY_PHOTON
|
||||
end select
|
||||
else
|
||||
call fatal_error("Missing library type")
|
||||
end if
|
||||
|
||||
! determine path of cross section table
|
||||
if (check_for_node(node_library, "path")) then
|
||||
call get_node_value(node_library, "path", temp_str)
|
||||
else
|
||||
call fatal_error("Missing library path")
|
||||
end if
|
||||
|
||||
if (starts_with(temp_str, '/')) then
|
||||
libraries(i) % path = trim(temp_str)
|
||||
else
|
||||
if (ends_with(directory,'/')) then
|
||||
libraries(i) % path = trim(directory) // trim(temp_str)
|
||||
else
|
||||
libraries(i) % path = trim(directory) // '/' // trim(temp_str)
|
||||
end if
|
||||
end if
|
||||
|
||||
inquire(FILE=libraries(i) % path, EXIST=file_exists)
|
||||
if (.not. file_exists) then
|
||||
call warning("Cross section library " // trim(libraries(i) % path) // &
|
||||
" does not exist.")
|
||||
end if
|
||||
end do
|
||||
|
||||
! Close cross sections XML file
|
||||
call doc % clear()
|
||||
|
||||
end subroutine read_ce_cross_sections_xml
|
||||
|
||||
subroutine read_mg_cross_sections_header()
|
||||
integer :: i ! loop index
|
||||
integer :: n_libraries
|
||||
logical :: file_exists ! does mgxs.h5 exist?
|
||||
integer(HID_T) :: file_id
|
||||
character(len=MAX_WORD_LEN), allocatable :: names(:)
|
||||
character(kind=C_CHAR), pointer :: string(:)
|
||||
|
||||
interface
|
||||
subroutine read_mg_cross_sections_header_c(file_id) bind(C)
|
||||
import HID_T
|
||||
integer(HID_T), value :: file_id
|
||||
end subroutine
|
||||
|
||||
function path_cross_sections_c() result(ptr) bind(C)
|
||||
import C_PTR
|
||||
type(C_PTR) :: ptr
|
||||
end function
|
||||
end interface
|
||||
|
||||
call c_f_pointer(path_cross_sections_c(), string, [255])
|
||||
path_cross_sections = to_f_string(string)
|
||||
|
||||
! Check if MGXS Library exists
|
||||
inquire(FILE=path_cross_sections, EXIST=file_exists)
|
||||
if (.not. file_exists) then
|
||||
|
|
@ -2244,24 +1982,6 @@ contains
|
|||
call set_particle_energy_bounds(NEUTRON, energy_min(NEUTRON), &
|
||||
energy_max(NEUTRON))
|
||||
|
||||
! Get the datasets present in the library
|
||||
call get_groups(file_id, names)
|
||||
n_libraries = size(names)
|
||||
|
||||
! Allocate libraries array
|
||||
if (n_libraries == 0) then
|
||||
call fatal_error("At least one MGXS data set must be present in &
|
||||
&mgxs library file!")
|
||||
else
|
||||
allocate(libraries(n_libraries))
|
||||
end if
|
||||
|
||||
do i = 1, n_libraries
|
||||
! Get name of material
|
||||
allocate(libraries(i) % materials(1))
|
||||
libraries(i) % materials(1) = names(i)
|
||||
end do
|
||||
|
||||
! Close MGXS HDF5 file
|
||||
call file_close(file_id)
|
||||
|
||||
|
|
@ -2350,7 +2070,6 @@ contains
|
|||
type(VectorReal), intent(in) :: sab_temps(:)
|
||||
|
||||
integer :: i, j
|
||||
integer :: i_library
|
||||
integer :: i_nuclide
|
||||
integer :: i_element
|
||||
integer :: i_sab
|
||||
|
|
@ -2358,6 +2077,7 @@ contains
|
|||
integer(HID_T) :: group_id
|
||||
logical :: mp_found ! if windowed multipole libraries were found
|
||||
character(MAX_WORD_LEN) :: name
|
||||
character(MAX_FILE_LEN) :: filename
|
||||
character(3) :: element
|
||||
type(SetChar) :: already_read
|
||||
type(SetChar) :: element_already_read
|
||||
|
|
@ -2375,14 +2095,14 @@ contains
|
|||
name = materials(i) % names(j)
|
||||
|
||||
if (.not. already_read % contains(name)) then
|
||||
i_library = library_dict % get(to_lower(name))
|
||||
filename = library_path(LIBRARY_NEUTRON, to_lower(name))
|
||||
i_nuclide = nuclide_dict % get(to_lower(name))
|
||||
|
||||
call write_message('Reading ' // trim(name) // ' from ' // &
|
||||
trim(libraries(i_library) % path), 6)
|
||||
trim(filename), 6)
|
||||
|
||||
! Open file and make sure version is sufficient
|
||||
file_id = file_open(libraries(i_library) % path, 'r')
|
||||
file_id = file_open(filename, 'r')
|
||||
call check_data_version(file_id)
|
||||
|
||||
! Read nuclide data from HDF5
|
||||
|
|
@ -2415,13 +2135,13 @@ contains
|
|||
if (photon_transport) then
|
||||
if (.not. element_already_read % contains(element)) then
|
||||
! Read photon interaction data from HDF5 photon library
|
||||
i_library = library_dict % get(to_lower(element))
|
||||
filename = library_path(LIBRARY_PHOTON, to_lower(element))
|
||||
i_element = element_dict % get(element)
|
||||
call write_message('Reading ' // trim(element) // ' from ' // &
|
||||
trim(libraries(i_library) % path), 6)
|
||||
trim(filename), 6)
|
||||
|
||||
! Open file and make sure version is sufficient
|
||||
file_id = file_open(libraries(i_library) % path, 'r')
|
||||
file_id = file_open(filename, 'r')
|
||||
call check_data_version(file_id)
|
||||
|
||||
! Read element data from HDF5
|
||||
|
|
@ -2505,14 +2225,14 @@ contains
|
|||
name = materials(i) % sab_names(j)
|
||||
|
||||
if (.not. already_read % contains(name)) then
|
||||
i_library = library_dict % get(to_lower(name))
|
||||
filename = library_path(LIBRARY_THERMAL, to_lower(name))
|
||||
i_sab = sab_dict % get(to_lower(name))
|
||||
|
||||
call write_message('Reading ' // trim(name) // ' from ' // &
|
||||
trim(libraries(i_library) % path), 6)
|
||||
trim(filename), 6)
|
||||
|
||||
! Open file and make sure version matches
|
||||
file_id = file_open(libraries(i_library) % path, 'r')
|
||||
file_id = file_open(filename, 'r')
|
||||
call check_data_version(file_id)
|
||||
|
||||
! Read S(a,b) data from HDF5
|
||||
|
|
@ -2556,9 +2276,8 @@ contains
|
|||
end if
|
||||
end do
|
||||
if (.not. mp_found) call warning("Windowed multipole functionality is &
|
||||
&turned on, but no multipole libraries were found. Set the &
|
||||
&<multipole_library> element in settings.xml or the &
|
||||
&OPENMC_MULTIPOLE_LIBRARY environment variable.")
|
||||
&turned on, but no multipole libraries were found. Make sure that &
|
||||
&windowed multipole data is present in your cross_sections.xml file.")
|
||||
end if
|
||||
|
||||
call already_read % clear()
|
||||
|
|
@ -2578,20 +2297,18 @@ contains
|
|||
logical :: file_exists ! Does multipole library exist?
|
||||
character(7) :: readable ! Is multipole library readable?
|
||||
character(MAX_FILE_LEN) :: filename ! Path to multipole xs library
|
||||
character(kind=C_CHAR), pointer :: string(:)
|
||||
integer(HID_T) :: file_id
|
||||
integer(HID_T) :: group_id
|
||||
|
||||
! For the time being, and I know this is a bit hacky, we just assume
|
||||
! that the file will be ZZZAAAmM.h5.
|
||||
associate (nuc => nuclides(i_table))
|
||||
|
||||
if (nuc % metastable > 0) then
|
||||
filename = trim(path_multipole) // trim(zero_padded(nuc % Z, 3)) // &
|
||||
trim(zero_padded(nuc % A, 3)) // 'm' // &
|
||||
trim(to_str(nuc % metastable)) // ".h5"
|
||||
! Look for WMP data in cross_sections.xml
|
||||
if (library_present(LIBRARY_WMP, to_lower(nuc % name))) then
|
||||
filename = library_path(LIBRARY_WMP, to_lower(nuc % name))
|
||||
else
|
||||
filename = trim(path_multipole) // trim(zero_padded(nuc % Z, 3)) // &
|
||||
trim(zero_padded(nuc % A, 3)) // ".h5"
|
||||
nuc % mp_present = .false.
|
||||
return
|
||||
end if
|
||||
|
||||
! Check if Multipole library exists and is readable
|
||||
|
|
@ -2605,7 +2322,8 @@ contains
|
|||
end if
|
||||
|
||||
! Display message
|
||||
call write_message("Loading Windowed Multipole XS from " // filename, 6)
|
||||
call write_message("Reading " // trim(nuc % name) // " WMP data from " &
|
||||
// filename, 6)
|
||||
|
||||
! Open file and make sure version is sufficient
|
||||
file_id = file_open(filename, 'r')
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ module material_header
|
|||
use sab_header
|
||||
use simulation_header, only: log_spacing
|
||||
use stl_vector, only: VectorReal, VectorInt
|
||||
use string, only: to_str
|
||||
use string, only: to_str, to_f_string
|
||||
|
||||
implicit none
|
||||
|
||||
|
|
@ -166,34 +166,52 @@ contains
|
|||
call material_set_fissionable_c(this % ptr, logical(fissionable, C_BOOL))
|
||||
end subroutine material_set_fissionable
|
||||
|
||||
function material_set_density(this, density) result(err)
|
||||
function material_set_density(this, density, units) result(err)
|
||||
class(Material), intent(inout) :: this
|
||||
real(8), intent(in) :: density
|
||||
character(*), intent(in) :: units
|
||||
integer :: err
|
||||
|
||||
integer :: i
|
||||
real(8) :: sum_percent
|
||||
real(8) :: awr
|
||||
real(8) :: previous_density_gpcc
|
||||
real(8) :: f
|
||||
|
||||
if (allocated(this % atom_density)) then
|
||||
! Set total density based on value provided
|
||||
this % density = density
|
||||
|
||||
! Determine normalized atom percents
|
||||
sum_percent = sum(this % atom_density)
|
||||
this % atom_density(:) = this % atom_density / sum_percent
|
||||
|
||||
! Recalculate nuclide atom densities based on given density
|
||||
this % atom_density(:) = density * this % atom_density
|
||||
|
||||
! Calculate density in g/cm^3.
|
||||
this % density_gpcc = ZERO
|
||||
do i = 1, this % n_nuclides
|
||||
awr = nuclides(this % nuclide(i)) % awr
|
||||
this % density_gpcc = this % density_gpcc &
|
||||
+ this % atom_density(i) * awr * MASS_NEUTRON / N_AVOGADRO
|
||||
end do
|
||||
err = 0
|
||||
select case (units)
|
||||
case ('atom/b-cm')
|
||||
! Set total density based on value provided
|
||||
this % density = density
|
||||
|
||||
! Determine normalized atom percents
|
||||
sum_percent = sum(this % atom_density)
|
||||
this % atom_density(:) = this % atom_density / sum_percent
|
||||
|
||||
! Recalculate nuclide atom densities based on given density
|
||||
this % atom_density(:) = density * this % atom_density
|
||||
|
||||
! Calculate density in g/cm^3.
|
||||
this % density_gpcc = ZERO
|
||||
do i = 1, this % n_nuclides
|
||||
awr = nuclides(this % nuclide(i)) % awr
|
||||
this % density_gpcc = this % density_gpcc &
|
||||
+ this % atom_density(i) * awr * MASS_NEUTRON / N_AVOGADRO
|
||||
end do
|
||||
case ('g/cm3', 'g/cc')
|
||||
! Determine factor by which to change densities
|
||||
previous_density_gpcc = this % density_gpcc
|
||||
f = density / previous_density_gpcc
|
||||
|
||||
! Update densities
|
||||
this % density_gpcc = density
|
||||
this % density = f * this % density
|
||||
this % atom_density(:) = f * this % atom_density(:)
|
||||
case default
|
||||
err = E_INVALID_ARGUMENT
|
||||
call set_errmsg("Invalid units '" // trim(units) // "' specified.")
|
||||
end select
|
||||
else
|
||||
err = E_ALLOCATE
|
||||
call set_errmsg("Material atom density array hasn't been allocated.")
|
||||
|
|
@ -738,16 +756,22 @@ contains
|
|||
end function openmc_material_set_id
|
||||
|
||||
|
||||
function openmc_material_set_density(index, density) result(err) bind(C)
|
||||
! Set the total density of a material in atom/b-cm
|
||||
function openmc_material_set_density(index, density, units) result(err) bind(C)
|
||||
! Set the total density of a material
|
||||
integer(C_INT32_T), value, intent(in) :: index
|
||||
real(C_DOUBLE), value, intent(in) :: density
|
||||
character(kind=C_CHAR), intent(in) :: units(*)
|
||||
integer(C_INT) :: err
|
||||
|
||||
character(:), allocatable :: units_
|
||||
|
||||
! Convert C string to Fortran string
|
||||
units_ = to_f_string(units)
|
||||
|
||||
err = E_UNASSIGNED
|
||||
if (index >= 1 .and. index <= size(materials)) then
|
||||
associate (m => materials(index))
|
||||
err = m % set_density(density)
|
||||
err = m % set_density(density, units_)
|
||||
end associate
|
||||
else
|
||||
err = E_OUT_OF_BOUNDS
|
||||
|
|
@ -794,7 +818,7 @@ contains
|
|||
m % n_nuclides = n
|
||||
|
||||
! Set total density to the sum of the vector
|
||||
err = m % set_density(sum(density))
|
||||
err = m % set_density(sum(density), 'atom/b-cm')
|
||||
|
||||
! Assign S(a,b) tables
|
||||
call m % assign_sab_tables()
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
#include "openmc/error.h"
|
||||
#include "openmc/math_functions.h"
|
||||
#include "openmc/random_lcg.h"
|
||||
#include "openmc/string_functions.h"
|
||||
#include "openmc/string_utils.h"
|
||||
|
||||
|
||||
namespace openmc {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include "openmc/cross_sections.h"
|
||||
#include "openmc/error.h"
|
||||
#include "openmc/math_functions.h"
|
||||
|
||||
|
|
@ -109,6 +110,20 @@ void read_mg_cross_sections_header_c(hid_t file_id)
|
|||
for (int i = 0; i < energy_bins.size() - 1; ++i) {
|
||||
energy_bin_avg.push_back(0.5*(energy_bins[i] + 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);
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ module nuclide_header
|
|||
use algorithm, only: sort, find, binary_search
|
||||
use constants
|
||||
use dict_header, only: DictIntInt, DictCharInt
|
||||
use endf, only: reaction_name, is_fission, is_disappearance
|
||||
use endf, only: reaction_name, is_fission, is_disappearance, &
|
||||
is_inelastic_scatter
|
||||
use endf_header, only: Function1D, Polynomial, Tabulated1D
|
||||
use error
|
||||
use hdf5_interface
|
||||
|
|
@ -176,20 +177,6 @@ module nuclide_header
|
|||
real(C_DOUBLE) :: pair_production ! macroscopic pair production xs
|
||||
end type MaterialMacroXS
|
||||
|
||||
!===============================================================================
|
||||
! LIBRARY contains data read from a cross_sections.xml file
|
||||
!===============================================================================
|
||||
|
||||
type Library
|
||||
integer :: type
|
||||
character(MAX_WORD_LEN), allocatable :: materials(:)
|
||||
character(MAX_FILE_LEN) :: path
|
||||
end type Library
|
||||
|
||||
! Cross section libraries
|
||||
type(Library), allocatable :: libraries(:)
|
||||
type(DictCharInt) :: library_dict
|
||||
|
||||
! Nuclear data for each nuclide
|
||||
type(Nuclide), allocatable, target :: nuclides(:)
|
||||
integer(C_INT), bind(C) :: n_nuclides
|
||||
|
|
@ -204,8 +191,46 @@ module nuclide_header
|
|||
real(8) :: energy_min(2) = [ZERO, ZERO]
|
||||
real(8) :: energy_max(2) = [INFINITY, INFINITY]
|
||||
|
||||
|
||||
interface
|
||||
function library_present_c(type, name) result(b) bind(C, name='library_present')
|
||||
import C_INT, C_CHAR, C_BOOL
|
||||
integer(C_INT), value :: type
|
||||
character(kind=C_CHAR), intent(in) :: name(*)
|
||||
logical(C_BOOL) :: b
|
||||
end function
|
||||
|
||||
function library_path_c(type, name) result(path) bind(C, name='library_path')
|
||||
import C_INT, C_CHAR, C_PTR
|
||||
integer(C_INT), value :: type
|
||||
character(kind=C_CHAR), intent(in) :: name(*)
|
||||
type(C_PTR) :: path
|
||||
end function
|
||||
end interface
|
||||
|
||||
contains
|
||||
|
||||
function library_path(type, name) result(path)
|
||||
integer, intent(in) :: type
|
||||
character(len=*), intent(in) :: name
|
||||
character(MAX_FILE_LEN) :: path
|
||||
|
||||
type(C_PTR) :: ptr
|
||||
character(kind=C_CHAR), pointer :: string(:)
|
||||
|
||||
ptr = library_path_c(type, to_c_string(name))
|
||||
call c_f_pointer(ptr, string, [255])
|
||||
path = to_f_string(string)
|
||||
end function
|
||||
|
||||
function library_present(type, name) result(b)
|
||||
integer, intent(in) :: type
|
||||
character(len=*), intent(in) :: name
|
||||
logical :: b
|
||||
|
||||
b = library_present_c(type, to_c_string(name))
|
||||
end function
|
||||
|
||||
!===============================================================================
|
||||
! ASSIGN_0K_ELASTIC_SCATTERING
|
||||
!===============================================================================
|
||||
|
|
@ -216,11 +241,30 @@ contains
|
|||
integer :: i
|
||||
real(8) :: xs_cdf_sum
|
||||
|
||||
interface
|
||||
function res_scat_nuclides_empty() result(empty) bind(C)
|
||||
import C_BOOL
|
||||
logical(C_BOOL) :: empty
|
||||
end function
|
||||
|
||||
function res_scat_nuclides_size() result(n) bind(C)
|
||||
import C_INT
|
||||
integer(C_INT) :: n
|
||||
end function
|
||||
|
||||
function res_scat_nuclides_cmp(i, name) result(b) bind(C)
|
||||
import C_INT, C_CHAR, C_BOOL
|
||||
integer(C_INT), value :: i
|
||||
character(kind=C_CHAR), intent(in) :: name(*)
|
||||
logical(C_BOOL) :: b
|
||||
end function
|
||||
end interface
|
||||
|
||||
this % resonant = .false.
|
||||
if (allocated(res_scat_nuclides)) then
|
||||
if (.not. res_scat_nuclides_empty()) then
|
||||
! If resonant nuclides were specified, check the list explicitly
|
||||
do i = 1, size(res_scat_nuclides)
|
||||
if (this % name == res_scat_nuclides(i)) then
|
||||
do i = 1, res_scat_nuclides_size()
|
||||
if (res_scat_nuclides_cmp(i, to_c_string(this % name))) then
|
||||
this % resonant = .true.
|
||||
|
||||
! Make sure nuclide has 0K data
|
||||
|
|
@ -486,12 +530,7 @@ contains
|
|||
|
||||
! Add the reaction index to the scattering array if this is an inelastic
|
||||
! scatter reaction
|
||||
if (MTs % data(i) /= N_FISSION .and. MTs % data(i) /= N_F .and. &
|
||||
MTs % data(i) /= N_NF .and. MTs % data(i) /= N_2NF .and. &
|
||||
MTs % data(i) /= N_3NF .and. MTs % data(i) < 200 .and. &
|
||||
MTs % data(i) /= N_LEVEL .and. MTs % data(i) /= ELASTIC .and. &
|
||||
.not. this % reactions(i) % redundant) then
|
||||
|
||||
if (is_inelastic_scatter(MTs % data(i))) then
|
||||
call index_inelastic_scatter % push_back(i)
|
||||
end if
|
||||
|
||||
|
|
@ -653,20 +692,10 @@ contains
|
|||
end if
|
||||
end do
|
||||
|
||||
! Skip total inelastic level scattering, gas production cross sections
|
||||
! (MT=200+), etc.
|
||||
if (rx % MT == N_LEVEL .or. rx % MT == N_NONELASTIC) cycle
|
||||
! Skip gas production cross sections (MT=200+), etc.
|
||||
if (rx % MT > N_5N2P .and. rx % MT < N_P0) cycle
|
||||
|
||||
! Skip level cross sections if total is available
|
||||
if (rx % MT >= N_P0 .and. rx % MT <= N_PC .and. find(MTs, N_P) /= -1) cycle
|
||||
if (rx % MT >= N_D0 .and. rx % MT <= N_DC .and. find(MTs, N_D) /= -1) cycle
|
||||
if (rx % MT >= N_T0 .and. rx % MT <= N_TC .and. find(MTs, N_T) /= -1) cycle
|
||||
if (rx % MT >= N_3HE0 .and. rx % MT <= N_3HEC .and. find(MTs, N_3HE) /= -1) cycle
|
||||
if (rx % MT >= N_A0 .and. rx % MT <= N_AC .and. find(MTs, N_A) /= -1) cycle
|
||||
if (rx % MT >= N_2N0 .and. rx % MT <= N_2NC .and. find(MTs, N_2N) /= -1) cycle
|
||||
|
||||
! Skip redundant reactions, which are used for photon production
|
||||
! Skip any reaction that has been marked as redundant
|
||||
if (rx % redundant) cycle
|
||||
|
||||
! Add contribution to total cross section
|
||||
|
|
@ -1540,6 +1569,11 @@ contains
|
|||
subroutine free_memory_nuclide()
|
||||
integer :: i
|
||||
|
||||
interface
|
||||
subroutine library_clear() bind(C)
|
||||
end subroutine
|
||||
end interface
|
||||
|
||||
! Deallocate cross section data, listings, and cache
|
||||
if (allocated(nuclides)) then
|
||||
! First call the clear routines
|
||||
|
|
@ -1550,10 +1584,8 @@ contains
|
|||
end if
|
||||
n_nuclides = 0
|
||||
|
||||
if (allocated(libraries)) deallocate(libraries)
|
||||
|
||||
call nuclide_dict % clear()
|
||||
call library_dict % clear()
|
||||
call library_clear()
|
||||
|
||||
end subroutine free_memory_nuclide
|
||||
|
||||
|
|
@ -1593,11 +1625,11 @@ contains
|
|||
character(kind=C_CHAR), intent(in) :: name(*)
|
||||
integer(C_INT) :: err
|
||||
|
||||
integer :: i_library
|
||||
integer :: n
|
||||
integer(HID_T) :: file_id
|
||||
integer(HID_T) :: group_id
|
||||
character(:), allocatable :: name_
|
||||
character(MAX_FILE_LEN) :: filename
|
||||
real(8) :: minmax(2) = [ZERO, INFINITY]
|
||||
type(VectorReal) :: temperature
|
||||
type(Nuclide), allocatable :: new_nuclides(:)
|
||||
|
|
@ -1607,7 +1639,7 @@ contains
|
|||
|
||||
err = 0
|
||||
if (.not. nuclide_dict % has(to_lower(name_))) then
|
||||
if (library_dict % has(to_lower(name_))) then
|
||||
if (library_present(LIBRARY_NEUTRON, to_lower(name_))) then
|
||||
! allocate extra space in nuclides array
|
||||
n = n_nuclides
|
||||
allocate(new_nuclides(n + 1))
|
||||
|
|
@ -1615,10 +1647,10 @@ contains
|
|||
call move_alloc(FROM=new_nuclides, TO=nuclides)
|
||||
n = n + 1
|
||||
|
||||
i_library = library_dict % get(to_lower(name_))
|
||||
filename = library_path(LIBRARY_NEUTRON, to_lower(name_))
|
||||
|
||||
! Open file and make sure version is sufficient
|
||||
file_id = file_open(libraries(i_library) % path, 'r')
|
||||
file_id = file_open(filename, 'r')
|
||||
call check_data_version(file_id)
|
||||
|
||||
! Read nuclide data from HDF5
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
#include "openmc/geometry.h"
|
||||
#include "openmc/cell.h"
|
||||
#include "openmc/material.h"
|
||||
#include "openmc/string_functions.h"
|
||||
#include "openmc/string_utils.h"
|
||||
#include "openmc/mesh.h"
|
||||
#include "openmc/output.h"
|
||||
#include "openmc/hdf5_interface.h"
|
||||
|
|
|
|||
|
|
@ -37,7 +37,5 @@ element materials {
|
|||
}*
|
||||
}+ &
|
||||
|
||||
element cross_sections { xsd:string { maxLength = "255" } }? &
|
||||
|
||||
element multipole_library { xsd:string { maxLength = "255" } }?
|
||||
element cross_sections { xsd:string { maxLength = "255" } }?
|
||||
}
|
||||
|
|
|
|||
|
|
@ -161,12 +161,5 @@
|
|||
</data>
|
||||
</element>
|
||||
</optional>
|
||||
<optional>
|
||||
<element name="multipole_library">
|
||||
<data type="string">
|
||||
<param name="maxLength">255</param>
|
||||
</data>
|
||||
</element>
|
||||
</optional>
|
||||
</interleave>
|
||||
</element>
|
||||
|
|
|
|||
|
|
@ -101,7 +101,6 @@ module settings
|
|||
|
||||
character(MAX_FILE_LEN) :: path_input ! Path to input file
|
||||
character(MAX_FILE_LEN) :: path_cross_sections = '' ! Path to cross_sections.xml
|
||||
character(MAX_FILE_LEN) :: path_multipole ! Path to wmp library
|
||||
character(MAX_FILE_LEN) :: path_state_point ! Path to binary state point
|
||||
character(MAX_FILE_LEN) :: path_source_point ! Path to binary source point
|
||||
character(MAX_FILE_LEN) :: path_particle_restart ! Path to particle restart
|
||||
|
|
@ -115,7 +114,6 @@ module settings
|
|||
integer(C_INT), bind(C) :: res_scat_method ! resonance scattering method
|
||||
real(C_DOUBLE), bind(C) :: res_scat_energy_min
|
||||
real(C_DOUBLE), bind(C) :: res_scat_energy_max
|
||||
character(10), allocatable :: res_scat_nuclides(:)
|
||||
|
||||
! Is CMFD active
|
||||
logical(C_BOOL), bind(C) :: cmfd_run
|
||||
|
|
@ -123,21 +121,4 @@ module settings
|
|||
! No reduction at end of batch
|
||||
logical(C_BOOL), bind(C) :: reduce_tallies
|
||||
|
||||
contains
|
||||
|
||||
!===============================================================================
|
||||
! FREE_MEMORY_SETTINGS deallocates global arrays defined in this module
|
||||
!===============================================================================
|
||||
|
||||
subroutine free_memory_settings()
|
||||
interface
|
||||
subroutine free_memory_settings_c() bind(C)
|
||||
end subroutine
|
||||
end interface
|
||||
|
||||
if (allocated(res_scat_nuclides)) deallocate(res_scat_nuclides)
|
||||
|
||||
call free_memory_settings_c()
|
||||
end subroutine free_memory_settings
|
||||
|
||||
end module settings
|
||||
|
|
|
|||
|
|
@ -63,7 +63,6 @@ bool dagmc {false};
|
|||
|
||||
std::string path_cross_sections;
|
||||
std::string path_input;
|
||||
std::string path_multipole;
|
||||
std::string path_output;
|
||||
std::string path_particle_restart;
|
||||
std::string path_source;
|
||||
|
|
@ -73,7 +72,7 @@ std::string path_statepoint;
|
|||
int32_t index_entropy_mesh {-1};
|
||||
int32_t index_ufs_mesh {-1};
|
||||
int32_t index_cmfd_mesh {-1};
|
||||
|
||||
|
||||
int32_t n_batches;
|
||||
int32_t n_inactive {0};
|
||||
int32_t gen_per_batch {1};
|
||||
|
|
@ -88,6 +87,7 @@ int n_max_batches;
|
|||
int res_scat_method {RES_SCAT_ARES};
|
||||
double res_scat_energy_min {0.01};
|
||||
double res_scat_energy_max {1000.0};
|
||||
std::vector<std::string> res_scat_nuclides;
|
||||
int run_mode {-1};
|
||||
std::unordered_set<int> sourcepoint_batch;
|
||||
std::unordered_set<int> statepoint_batch;
|
||||
|
|
@ -187,7 +187,7 @@ void read_settings_xml()
|
|||
using namespace pugi;
|
||||
|
||||
// Check if settings.xml exists
|
||||
std::string filename = std::string(path_input) + "settings.xml";
|
||||
std::string filename = path_input + "settings.xml";
|
||||
if (!file_exists(filename)) {
|
||||
if (run_mode != RUN_MODE_PLOTTING) {
|
||||
std::stringstream msg;
|
||||
|
|
@ -256,21 +256,6 @@ void read_settings_xml()
|
|||
path_cross_sections = get_node_value(root, "cross_sections");
|
||||
}
|
||||
|
||||
// Look for deprecated windowed_multipole file in settings.xml
|
||||
if (run_mode != RUN_MODE_PLOTTING) {
|
||||
if (check_for_node(root, "multipole_library")) {
|
||||
warning("Setting multipole_library in settings.xml has been "
|
||||
"deprecated. The multipole_library is now set in materials.xml and"
|
||||
" the multipole_library input to materials.xml and the "
|
||||
"OPENMC_MULTIPOLE_LIBRARY environment variable will take "
|
||||
"precendent over setting multipole_library in settings.xml.");
|
||||
path_multipole = get_node_value(root, "multipole_library");
|
||||
}
|
||||
if (!ends_with(path_multipole, "/")) {
|
||||
path_multipole += "/";
|
||||
}
|
||||
}
|
||||
|
||||
if (!run_CE) {
|
||||
// Scattering Treatments
|
||||
if (check_for_node(root, "max_order")) {
|
||||
|
|
@ -749,7 +734,10 @@ void read_settings_xml()
|
|||
"lower resonance scattering energy bound.");
|
||||
}
|
||||
|
||||
// TODO: Get resonance scattering nuclides
|
||||
// Get resonance scattering nuclides
|
||||
if (check_for_node(node_res_scat, "nuclides")) {
|
||||
res_scat_nuclides = get_node_array<std::string>(node_res_scat, "nuclides");
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Get volume calculations
|
||||
|
|
@ -817,22 +805,38 @@ void read_settings_xml()
|
|||
//==============================================================================
|
||||
|
||||
extern "C" {
|
||||
const char* openmc_path_input() {
|
||||
bool res_scat_nuclides_empty() {
|
||||
return settings::res_scat_nuclides.empty();
|
||||
}
|
||||
|
||||
int res_scat_nuclides_size() {
|
||||
return settings::res_scat_nuclides.size();
|
||||
}
|
||||
|
||||
bool res_scat_nuclides_cmp(int i, const char* name) {
|
||||
return settings::res_scat_nuclides[i - 1] == name;
|
||||
}
|
||||
|
||||
const char* path_cross_sections_c() {
|
||||
return settings::path_cross_sections.c_str();
|
||||
}
|
||||
const char* path_input_c() {
|
||||
return settings::path_input.c_str();
|
||||
}
|
||||
const char* openmc_path_statepoint() {
|
||||
const char* path_statepoint_c() {
|
||||
return settings::path_statepoint.c_str();
|
||||
}
|
||||
const char* openmc_path_sourcepoint() {
|
||||
const char* path_sourcepoint_c() {
|
||||
return settings::path_sourcepoint.c_str();
|
||||
}
|
||||
const char* openmc_path_particle_restart() {
|
||||
const char* path_particle_restart_c() {
|
||||
return settings::path_particle_restart.c_str();
|
||||
}
|
||||
|
||||
void free_memory_settings_c() {
|
||||
void free_memory_settings() {
|
||||
settings::statepoint_batch.clear();
|
||||
settings::sourcepoint_batch.clear();
|
||||
settings::res_scat_nuclides.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,40 +0,0 @@
|
|||
#include "openmc/string_functions.h"
|
||||
#include <sstream>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
} // namespace openmc
|
||||
78
src/string_utils.cpp
Normal file
78
src/string_utils.cpp
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
#include "openmc/string_utils.h"
|
||||
|
||||
#include <algorithm> // for equal
|
||||
#include <cctype> // for tolower, isspace
|
||||
#include <sstream>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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<std::string> split(const std::string& in)
|
||||
{
|
||||
std::vector<std::string> 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
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
#include "openmc/error.h"
|
||||
#include "openmc/hdf5_interface.h"
|
||||
#include "openmc/xml_interface.h"
|
||||
#include "openmc/string_functions.h"
|
||||
#include "openmc/string_utils.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
bd3fd10177bc0c7b8542f15228decf8608de013872d201e6ae885cf9b5b6d7516ddb32044ee2f7fd5b207e7d37d5ce3f03e347a2e850953bba4fc26b150c89d2
|
||||
4b75e203d06d0fc1b4c4dfcb8c180d6f3df8fa2bc44e9775b59bbfd8f7a3785f956f9a9f301526f69c0f8a963ce2e553e0c62c7f6c696656ce1d47b415af6076
|
||||
|
|
@ -438,7 +438,7 @@ cmfd balance
|
|||
0.000000E+00
|
||||
0.000000E+00
|
||||
4.009062E-03
|
||||
4.869662E-03
|
||||
4.869661E-03
|
||||
2.997290E-03
|
||||
2.711191E-03
|
||||
1.688329E-03
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,5 +1,5 @@
|
|||
d_material,d_nuclide,d_variable,score,mean,std. dev.
|
||||
3,,density,flux,-4.7291290e+00,8.8503902e-01
|
||||
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
|
||||
|
|
@ -11,16 +11,16 @@ d_material,d_nuclide,d_variable,score,mean,std. dev.
|
|||
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.7048498e+00,3.3363896e-01
|
||||
3,,density,fission,1.3210039e-01,1.6377610e-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.8974770e-03
|
||||
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.2864288e-01,1.3031728e-01
|
||||
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
|
||||
|
|
@ -31,17 +31,17 @@ d_material,d_nuclide,d_variable,score,mean,std. dev.
|
|||
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.8519873e-02
|
||||
1,,density,fission,-4.4865588e-03,2.3660449e-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.6990351e-03,3.5138725e-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.9802045e-04
|
||||
1,,density,fission,-6.3630708e-03,2.3832611e-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.1430498e-03,4.0831822e-03
|
||||
1,,density,scatter,-5.4829026e-01,5.7756112e-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
|
||||
|
|
@ -50,17 +50,17 @@ d_material,d_nuclide,d_variable,score,mean,std. dev.
|
|||
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.5302455e-01
|
||||
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.7382098e-01,3.1002267e-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.5539605e+01,2.3345398e+01
|
||||
1,O16,nuclide_density,absorption,-8.5880168e-02,5.0677339e-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
|
||||
|
|
@ -78,10 +78,10 @@ d_material,d_nuclide,d_variable,score,mean,std. dev.
|
|||
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.5228268e+02,5.9109738e+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.3502263e+02
|
||||
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
|
||||
|
|
@ -109,11 +109,11 @@ d_material,d_nuclide,d_variable,score,mean,std. dev.
|
|||
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.1512672e-02,2.4627803e-01
|
||||
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.0238428e+00,3.5596763e-01
|
||||
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
|
||||
|
|
@ -139,7 +139,7 @@ d_material,d_nuclide,d_variable,score,mean,std. dev.
|
|||
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.3723982e-02,1.5246898e-02
|
||||
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
|
||||
|
|
@ -153,7 +153,7 @@ d_material,d_nuclide,d_variable,score,mean,std. dev.
|
|||
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.8199870e-01,1.6570982e+00
|
||||
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
|
||||
|
|
|
|||
|
|
@ -113,9 +113,6 @@ class DiffTallyTestHarness(PyAPITestHarness):
|
|||
return df.to_csv(None, columns=cols, index=False, float_format='%.7e')
|
||||
|
||||
|
||||
@pytest.mark.skipif('OPENMC_MULTIPOLE_LIBRARY' not in os.environ,
|
||||
reason='OPENMC_MULTIPOLE_LIBRARY environment variable '
|
||||
'must be set')
|
||||
def test_diff_tally():
|
||||
harness = DiffTallyTestHarness('statepoint.3.h5')
|
||||
harness.main()
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
a1f6ccf0bef1075ffc12e7fa058a44c83360801ba6e2c76f00e1bd7e9543fe1832777b122321dcb1cfb5fc1165ce84f711a65ca83903dd57cd09652e003daf62
|
||||
11755ecac8355b5e79384f5d72974e618b6f95500c0a5718c01bb340c5d1c8ceafc33de65b9e94b7e9d78f16ec209f8a0fdf6a531eab5430657688d0125db7ef
|
||||
|
|
@ -1 +1 @@
|
|||
46950c046648faaa5ff3cb7b4fdd03667ae3c6da96a7ed8121761291de452cf88481f53e967ed52407d77d90109ae24839967a22ae216531a0e1491f5051ea72
|
||||
cc306dfd3e3669827cb2f3bdc38005c0616f6faecb9277f3b0f869fdecf826ae662c65d67a402705956f100d2e13c7c11332364fa41ccc2e215ab100709b627f
|
||||
|
|
@ -1,2 +1,2 @@
|
|||
k-combined:
|
||||
2.546817E-01 1.509389E-02
|
||||
2.562946E-01 1.530982E-02
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
k-combined:
|
||||
1.006646E+00 1.477915E-02
|
||||
9.877395E-01 1.744626E-02
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
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.468222
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@
|
|||
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.24765
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -1,35 +1,35 @@
|
|||
domain=1 type=total
|
||||
[4.14825464e-01 6.60169863e-01]
|
||||
[2.27929105e-02 4.75188999e-02]
|
||||
[2.27929104e-02 4.75189000e-02]
|
||||
domain=1 type=transport
|
||||
[3.63092031e-01 6.44850709e-01]
|
||||
[2.38384843e-02 4.76746408e-02]
|
||||
[2.38384842e-02 4.76746410e-02]
|
||||
domain=1 type=nu-transport
|
||||
[3.63092031e-01 6.44850709e-01]
|
||||
[2.38384843e-02 4.76746408e-02]
|
||||
[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.98445483e-02 7.17193458e-02]
|
||||
[1.98445482e-02 7.17193458e-02]
|
||||
[2.64330389e-03 2.52078411e-02]
|
||||
domain=1 type=fission
|
||||
[7.56329483e-03 1.92791369e-01]
|
||||
[5.08483896e-04 1.71059103e-02]
|
||||
[7.56329484e-03 1.92791369e-01]
|
||||
[5.08483893e-04 1.71059103e-02]
|
||||
domain=1 type=nu-fission
|
||||
[1.94317397e-02 4.69774728e-01]
|
||||
[1.32297611e-03 4.16819716e-02]
|
||||
[1.32297610e-03 4.16819717e-02]
|
||||
domain=1 type=kappa-fission
|
||||
[1.47456979e+06 3.72868925e+07]
|
||||
[9.92353629e+04 3.30837549e+06]
|
||||
[9.92353624e+04 3.30837549e+06]
|
||||
domain=1 type=scatter
|
||||
[3.87417621e-01 3.95659148e-01]
|
||||
[2.06257343e-02 2.51250447e-02]
|
||||
[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.47771503e-03]
|
||||
[[[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]
|
||||
|
|
@ -40,7 +40,7 @@ domain=1 type=scatter matrix
|
|||
[[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.47771503e-03]
|
||||
[[[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]
|
||||
|
|
@ -59,7 +59,7 @@ 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.74255162e-02 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]]
|
||||
|
|
@ -71,52 +71,52 @@ domain=1 type=consistent scatter matrix
|
|||
|
||||
[[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.76748968e-03 3.13767806e-03 2.32683668e-03]
|
||||
[4.89318749e-04 1.50458419e-04 1.85500930e-04 1.29783344e-04]]
|
||||
[[[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.98710064e-02 4.44330993e-03 1.01307463e-02 1.00367467e-02]]]
|
||||
[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.51522200e-03 2.44425169e-03]
|
||||
[[[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.39988352e-02 4.49065920e-03 1.01338659e-02 1.00452944e-02]]]
|
||||
[3.39988353e-02 4.49065920e-03 1.01338659e-02 1.00452944e-02]]]
|
||||
domain=1 type=chi
|
||||
[1.00000000e+00 0.00000000e+00]
|
||||
[4.60705493e-02 0.00000000e+00]
|
||||
[4.60705491e-02 0.00000000e+00]
|
||||
domain=1 type=chi-prompt
|
||||
[1.00000000e+00 0.00000000e+00]
|
||||
[5.14714845e-02 0.00000000e+00]
|
||||
[5.14714842e-02 0.00000000e+00]
|
||||
domain=1 type=inverse-velocity
|
||||
[5.70932437e-08 2.85573948e-06]
|
||||
[4.68793810e-09 2.44216368e-07]
|
||||
[4.68793809e-09 2.44216369e-07]
|
||||
domain=1 type=prompt-nu-fission
|
||||
[1.92392209e-02 4.66718979e-01]
|
||||
[1.30950644e-03 4.14108424e-02]
|
||||
[1.30950644e-03 4.14108425e-02]
|
||||
domain=1 type=prompt-nu-fission matrix
|
||||
[[2.01424221e-02 0.00000000e+00]
|
||||
[4.45819055e-01 0.00000000e+00]]
|
||||
[4.45819054e-01 0.00000000e+00]]
|
||||
[[3.14909051e-03 0.00000000e+00]
|
||||
[2.86750878e-02 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.02983423e-04]]
|
||||
[[2.89748553e-07 9.49155601e-06]
|
||||
[1.85003751e-06 4.89925095e-05]
|
||||
[1.97097930e-06 4.67725251e-05]
|
||||
[5.22610330e-06 1.04867938e-04]
|
||||
[2.99830756e-06 4.29944539e-05]
|
||||
[1.22654681e-06 1.80102228e-05]]
|
||||
[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]
|
||||
|
|
@ -136,13 +136,13 @@ domain=1 type=beta
|
|||
[1.46341397e-03 1.12212853e-03]
|
||||
[3.82159878e-03 2.51590670e-03]
|
||||
[2.13520982e-03 1.03148823e-03]
|
||||
[8.74939593e-04 4.32086725e-04]]
|
||||
[[1.80847602e-05 2.46946655e-05]
|
||||
[8.74939592e-04 4.32086725e-04]]
|
||||
[[1.80847601e-05 2.46946655e-05]
|
||||
[1.14688936e-04 1.27466313e-04]
|
||||
[1.21787672e-04 1.21690467e-04]
|
||||
[3.21434953e-04 2.72840272e-04]
|
||||
[1.82980531e-04 1.11860871e-04]
|
||||
[7.48900067e-05 4.68581181e-05]]
|
||||
[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]
|
||||
|
|
@ -150,12 +150,12 @@ domain=1 type=decay-rate
|
|||
[3.15269336e-01 3.02780066e-01]
|
||||
[8.89232587e-01 8.49490287e-01]
|
||||
[2.98940409e+00 2.85300088e+00]]
|
||||
[[1.08439456e-03 1.44623725e-03]
|
||||
[2.65795039e-03 3.55041661e-03]
|
||||
[1.02955037e-02 1.30981202e-02]
|
||||
[2.71748572e-02 3.28353145e-02]
|
||||
[7.93682892e-02 9.21238900e-02]
|
||||
[2.66253284e-01 3.09396760e-01]]
|
||||
[[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]]
|
||||
|
|
@ -178,7 +178,7 @@ domain=1 type=delayed-nu-fission matrix
|
|||
[0.00000000e+00 0.00000000e+00]]
|
||||
|
||||
[[0.00000000e+00 0.00000000e+00]
|
||||
[1.56094522e-03 0.00000000e+00]]
|
||||
[1.56094521e-03 0.00000000e+00]]
|
||||
|
||||
[[0.00000000e+00 0.00000000e+00]
|
||||
[1.18610370e-03 0.00000000e+00]]
|
||||
|
|
@ -192,20 +192,20 @@ domain=1 type=delayed-nu-fission matrix
|
|||
[[0.00000000e+00 0.00000000e+00]
|
||||
[0.00000000e+00 0.00000000e+00]]]
|
||||
domain=2 type=total
|
||||
[3.13737666e-01 3.00821380e-01]
|
||||
[1.55819223e-02 2.80524816e-02]
|
||||
[3.13737667e-01 3.00821380e-01]
|
||||
[1.55819228e-02 2.80524816e-02]
|
||||
domain=2 type=transport
|
||||
[2.75508079e-01 3.12035015e-01]
|
||||
[1.77418855e-02 3.23843473e-02]
|
||||
[1.77418859e-02 3.23843473e-02]
|
||||
domain=2 type=nu-transport
|
||||
[2.75508079e-01 3.12035015e-01]
|
||||
[1.77418855e-02 3.23843473e-02]
|
||||
[1.77418859e-02 3.23843473e-02]
|
||||
domain=2 type=absorption
|
||||
[1.57499139e-03 5.40037826e-03]
|
||||
[3.22547919e-04 6.18139027e-04]
|
||||
[1.57499139e-03 5.40037825e-03]
|
||||
[3.22547917e-04 6.18139027e-04]
|
||||
domain=2 type=capture
|
||||
[1.57499139e-03 5.40037826e-03]
|
||||
[3.22547919e-04 6.18139027e-04]
|
||||
[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]
|
||||
|
|
@ -217,7 +217,7 @@ domain=2 type=kappa-fission
|
|||
[0.00000000e+00 0.00000000e+00]
|
||||
domain=2 type=scatter
|
||||
[3.12162675e-01 2.95421002e-01]
|
||||
[1.53219430e-02 2.74455213e-02]
|
||||
[1.53219435e-02 2.74455213e-02]
|
||||
domain=2 type=nu-scatter
|
||||
[3.10120713e-01 2.96264249e-01]
|
||||
[3.37881037e-02 4.37922226e-02]
|
||||
|
|
@ -264,7 +264,7 @@ domain=2 type=consistent scatter matrix
|
|||
|
||||
[[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.72534018e-02 8.74305413e-03 4.83468235e-03 3.77642682e-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]
|
||||
|
|
@ -275,7 +275,7 @@ domain=2 type=consistent nu-scatter matrix
|
|||
|
||||
[[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.04070427e-02 9.69345877e-03 5.34169555e-03 3.87580585e-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]
|
||||
|
|
@ -287,8 +287,8 @@ domain=2 type=chi-prompt
|
|||
[0.00000000e+00 0.00000000e+00]
|
||||
[0.00000000e+00 0.00000000e+00]
|
||||
domain=2 type=inverse-velocity
|
||||
[5.99597929e-08 2.98549016e-06]
|
||||
[4.55308445e-09 3.41701982e-07]
|
||||
[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]
|
||||
|
|
@ -385,8 +385,8 @@ domain=2 type=delayed-nu-fission matrix
|
|||
[[0.00000000e+00 0.00000000e+00]
|
||||
[0.00000000e+00 0.00000000e+00]]]
|
||||
domain=3 type=total
|
||||
[6.64572195e-01 2.05238389e+00]
|
||||
[3.12147473e-02 2.24342891e-01]
|
||||
[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]
|
||||
|
|
@ -394,11 +394,11 @@ domain=3 type=nu-transport
|
|||
[2.83322749e-01 1.49973953e+00]
|
||||
[3.52061127e-02 2.30902118e-01]
|
||||
domain=3 type=absorption
|
||||
[6.90399495e-04 3.16872549e-02]
|
||||
[4.41475663e-05 3.74655831e-03]
|
||||
[6.90399488e-04 3.16872537e-02]
|
||||
[4.41475703e-05 3.74655812e-03]
|
||||
domain=3 type=capture
|
||||
[6.90399495e-04 3.16872549e-02]
|
||||
[4.41475663e-05 3.74655831e-03]
|
||||
[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]
|
||||
|
|
@ -418,24 +418,24 @@ 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.99960386e-04 3.19562684e-04 2.13846954e-04]
|
||||
[2.03494484e+00 5.09940477e-01 1.11174601e-01 2.49884339e-02]]]
|
||||
[[[2.47091210e-02 1.62432638e-02 8.15627712e-03 3.88856186e-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.31235197e-03]]]
|
||||
[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.99960386e-04 3.19562684e-04 2.13846954e-04]
|
||||
[2.03494484e+00 5.09940477e-01 1.11174601e-01 2.49884339e-02]]]
|
||||
[[[2.47091210e-02 1.62432638e-02 8.15627712e-03 3.88856186e-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.31235197e-03]]]
|
||||
[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]]
|
||||
|
|
@ -469,7 +469,7 @@ domain=3 type=consistent nu-scatter matrix
|
|||
[[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.15855775e-03 1.02420876e-03 8.64382873e-04]]
|
||||
[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]]]
|
||||
|
|
|
|||
|
|
@ -42,10 +42,10 @@
|
|||
3 2 2 1 1 total 0.020469 0.002617
|
||||
mesh 1 group in nuclide mean std. dev.
|
||||
x y z
|
||||
0 1 1 1 1 total 2.177345e+06 589804.299388
|
||||
2 1 2 1 1 total 1.404096e+06 236476.851953
|
||||
1 2 1 1 1 total 1.413154e+06 347806.623417
|
||||
3 2 2 1 1 total 1.608259e+06 206502.707865
|
||||
0 1 1 1 1 total 2.177345e+06 589804.301157
|
||||
2 1 2 1 1 total 1.404096e+06 236476.852674
|
||||
1 2 1 1 1 total 1.413154e+06 347806.623478
|
||||
3 2 2 1 1 total 1.608259e+06 206502.707123
|
||||
mesh 1 group in nuclide mean std. dev.
|
||||
x y z
|
||||
0 1 1 1 1 total 0.735256 0.080216
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@
|
|||
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.850038e-06
|
||||
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
|
||||
|
|
@ -325,7 +325,7 @@
|
|||
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.553084e-09
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
0edd3036c0b5b1eebad90dc8fba25006f14745ceb51dd109e70d0c610d66071f32128facdbc6d4e5077534fe96fff9a8e0ddeefb4a18d6c578f8e805bab7aa22
|
||||
185e6f1f7ba94b0cdfae5b2519865efec84055d341bd490b856f9786ef1c91a3cb007d6b22811ffa30d4665256aad8a2982548e6c96e8d8d9c5f569475e52cfe
|
||||
|
|
@ -74,9 +74,6 @@ class MultipoleTestHarness(PyAPITestHarness):
|
|||
return outstr
|
||||
|
||||
|
||||
@pytest.mark.skipif('OPENMC_MULTIPOLE_LIBRARY' not in os.environ,
|
||||
reason='OPENMC_MULTIPOLE_LIBRARY environment variable '
|
||||
'must be set')
|
||||
def test_multipole():
|
||||
model = make_model()
|
||||
harness = MultipoleTestHarness('statepoint.5.h5', model)
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
k-combined:
|
||||
1.040109E+00 6.527468E-02
|
||||
1.040109E+00 6.527466E-02
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
8cf1936c565c6a09bffe2f7a0623ded1405bae37c1de8159551e64b86ca4f6bce82890a630b9428bcf8353f6de8e5cfc1f1a4263fd51a1c6b5cddb0a9c2ff368
|
||||
aa7f79718620c122e3a13bfa0e200a41b642b09a5d10a6e43e1584181b0314fbeb73c165fe55ddd34c1e9546e381019dd8e3889ca7d99bfe1ab489631bec15d1
|
||||
|
|
@ -1 +1 @@
|
|||
c8fb043c5321e698040544dbb0baa9ce82df0e189738fb6013b4f3ff7e05a989a7a59b9b55034b8c9de6bc604ba9f969dc08ad2752fc74da205c19ff5974c9a2
|
||||
eac8fb56a8146b9e186ac9fb003753f4a0a18d4159d10e6fa51da4856baef66a10a0f5fb10c5727b51c6e44d81c147a8a7348ad9c9f7119a6ec33e0361082376
|
||||
|
|
@ -105,6 +105,9 @@ def test_material(capi_init):
|
|||
m.volume = 10.0
|
||||
assert m.volume == 10.0
|
||||
|
||||
with pytest.raises(exc.InvalidArgumentError):
|
||||
m.set_density(1.0, 'goblins')
|
||||
|
||||
rho = 2.25e-2
|
||||
m.set_density(rho)
|
||||
assert sum(m.densities) == pytest.approx(rho)
|
||||
|
|
|
|||
|
|
@ -1,25 +1,23 @@
|
|||
import os
|
||||
import pathlib
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
import openmc.data
|
||||
pytestmark = pytest.mark.skipif(
|
||||
'OPENMC_MULTIPOLE_LIBRARY' not in os.environ,
|
||||
reason='OPENMC_MULTIPOLE_LIBRARY environment variable must be set')
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def u235():
|
||||
directory = os.environ['OPENMC_MULTIPOLE_LIBRARY']
|
||||
filename = os.path.join(directory, '092235.h5')
|
||||
return openmc.data.WindowedMultipole.from_hdf5(filename)
|
||||
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 = os.environ['OPENMC_MULTIPOLE_LIBRARY']
|
||||
filename = os.path.join(directory, '005010.h5')
|
||||
return openmc.data.WindowedMultipole.from_hdf5(filename)
|
||||
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):
|
||||
|
|
|
|||
|
|
@ -154,7 +154,6 @@ def test_materials(run_in_tmpdir):
|
|||
|
||||
mats = openmc.Materials([m1, m2])
|
||||
mats.cross_sections = '/some/fake/cross_sections.xml'
|
||||
mats.multipole_library = '/some/awesome/mp_lib/'
|
||||
mats.export_to_xml()
|
||||
|
||||
|
||||
|
|
@ -200,7 +199,6 @@ def test_from_xml(run_in_tmpdir):
|
|||
|
||||
mats = openmc.Materials([m1, m2, m3])
|
||||
mats.cross_sections = 'fake_path.xml'
|
||||
mats.multipole_library = 'fake_multipole/'
|
||||
mats.export_to_xml()
|
||||
|
||||
# Regenerate materials from XML
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ def test_export_to_xml(run_in_tmpdir):
|
|||
s.statepoint = {'batches': [50, 150, 500, 1000]}
|
||||
s.confidence_intervals = True
|
||||
s.cross_sections = '/path/to/cross_sections.xml'
|
||||
s.multipole_library = '/path/to/wmp/'
|
||||
s.ptables = True
|
||||
s.run_cmfd = False
|
||||
s.seed = 17
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
#!/bin/bash
|
||||
set -ex
|
||||
|
||||
# Download NNDC HDF5 data
|
||||
# Download HDF5 data
|
||||
if [[ ! -e $HOME/nndc_hdf5/cross_sections.xml ]]; then
|
||||
wget -q -O - https://anl.box.com/shared/static/a0eflty17atnpd0pp7460exagr3nuhm7.xz | tar -C $HOME -xJ
|
||||
wget -q -O - https://anl.box.com/shared/static/snrluuy79o2fffpvpng9bsuis5kl811d.xz | tar -C $HOME -xJ
|
||||
fi
|
||||
|
||||
# Download ENDF/B-VII.1 distribution
|
||||
|
|
@ -11,9 +11,3 @@ 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
|
||||
|
||||
# Download multipole library
|
||||
if [[ ! -e $HOME/WMP_Library/092235.h5 ]]; then
|
||||
wget -q https://github.com/mit-crpg/WMP_Library/releases/download/v1.1/WMP_Library_v1.1.tar.gz
|
||||
tar -C $HOME -xzf WMP_Library_v1.1.tar.gz
|
||||
fi
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue