diff --git a/.travis.yml b/.travis.yml index 4236c36d1..676bfb42f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,7 @@ before_install: - conda config --set always_yes yes --set changeps1 no - conda update -q conda - conda info -a - - conda create -q -n test-environment python=$TRAVIS_PYTHON_VERSION numpy scipy h5py=2.5 pandas + - conda create -q -n test-environment python=$TRAVIS_PYTHON_VERSION six numpy scipy h5py=2.5 pandas - source activate test-environment # Install GCC, MPICH, HDF5, PHDF5 @@ -47,11 +47,9 @@ before_script: fi - export OPENMC_CROSS_SECTIONS=$HOME/nndc_hdf5/cross_sections.xml - - cd data - git clone --branch=master git://github.com/smharper/windowed_multipole_library.git wmp_lib - tar xzvf wmp_lib/multipole_lib.tar.gz - export OPENMC_MULTIPOLE_LIBRARY=$PWD/multipole_lib - - cd .. script: - cd tests diff --git a/data/readme.rst b/data/readme.rst deleted file mode 100644 index 03685491d..000000000 --- a/data/readme.rst +++ /dev/null @@ -1,37 +0,0 @@ -======================== -cross_sections.xml Files -======================== - -As a reminder, in order to run a simulation with OpenMC, you will need cross -section data for each nuclide in your problem. OpenMC is not currently -distributed with cross section data, so you will have to obtain cross section -data by other means. The `user's guide`_ offers some helpful advice on how you -can obtain cross sections. - -When OpenMC starts up, it needs a cross_sections.xml file that tells it where to -find ACE format cross sections. The files in this directory are configured to -work with a few common cross section sources. - -- **cross_sections_ascii.xml** -- This file matches ENDF/B-VII.0 cross sections - distributed with MCNP5 / MCNP6 beta. - -- **cross_sections_nndc.xml** -- This file matches ENDF/B-VII.1 cross sections - distributed from the `NNDC website`_. - -- **cross_sections_serpent.xml** -- This file matches ENDF/B-VII.0 cross - sections distributed with Serpent 1.1.7. - -- **cross_sections.xml** - This file matches ENDF/B-VII.0 cross sections - distributed with MCNP5 / MCNP6 beta *that have been converted to binary*. - -To use any of these files, you need to follow two steps: - -1. Change the path on the ```` element in the cross_sections.xml file -to the directory containing the ACE files. - -2. Enter the absolute path of the cross_sections.xml on the ```` -element in your settings.xml, or set the CROSS_SECTIONS environment variable to -the full path of the cross_sections.xml file. - -.. _user's guide: http://mit-crpg.github.io/openmc/usersguide/install.html#cross-section-configuration -.. _NNDC website: http://www.nndc.bnl.gov/endf/b7.1/acefiles.html diff --git a/docs/source/quickinstall.rst b/docs/source/quickinstall.rst index 7faa4978d..8e970d958 100644 --- a/docs/source/quickinstall.rst +++ b/docs/source/quickinstall.rst @@ -8,6 +8,26 @@ This quick install guide outlines the basic steps needed to install OpenMC on your computer. For more detailed instructions on configuring and installing OpenMC, see :ref:`usersguide_install` in the User's Manual. +---------------------------------------- +Installing on Linux/Mac with conda-forge +---------------------------------------- + +`Conda `_ is an open source package management +system and environment management system for installing multiple versions of +software packages and their dependencies and switching easily between them. If +you have `conda` installed on your system, OpenMC can be installed via the +`conda-forge` channel. First, add the `conda-forge` channel with: + +.. code-block:: sh + + conda config --add channels conda-forge + +OpenMC can then be installed with: + +.. code-block:: sh + + conda install openmc + -------------------------------- Installing on Ubuntu through PPA -------------------------------- diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index 925008495..bc5cbfadf 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -4,6 +4,38 @@ Installation and Configuration ============================== +---------------------------------------- +Installing on Linux/Mac with conda-forge +---------------------------------------- + +`Conda `_ is an open source package management +system and environment management system for installing multiple versions of +software packages and their dependencies and switching easily between +them. `conda-forge `_ is a community-led conda +channel of installable packages. For instructions on installing conda, please +consult their `documentation +`_. + +Once you have `conda` installed on your system, add the `conda-forge` channel to +your configuration with: + +.. code-block:: sh + + conda config --add channels conda-forge + +Once the `conda-forge` channel has been enabled, OpenMC can then be installed +with: + +.. code-block:: sh + + conda install openmc + +It is possible to list all of the versions of OpenMC available on your platform with: + +.. code-block:: sh + + conda search openmc --channel conda-forge + ----------------------------- Installing on Ubuntu with PPA ----------------------------- @@ -407,13 +439,11 @@ extract the ACE data, fix any deficiencies, and create an HDF5 library: .. code-block:: sh - cd openmc/data - python get_nndc_data.py + openmc-get-nndc-data At this point, you should set the :envvar:`OPENMC_CROSS_SECTIONS` environment -variable to the absolute path of the file -``openmc/data/nndc_hdf5/cross_sections.xml``. This cross section set is used by -the test suite. +variable to the absolute path of the file ``nndc_hdf5/cross_sections.xml``. This +cross section set is used by the test suite. Using JEFF Cross Sections from OECD/NEA --------------------------------------- @@ -424,12 +454,10 @@ and extract the ACE data, fix any deficiencies, and create an HDF5 library. .. code-block:: sh - cd openmc/data - python get_jeff_data.py + openmc-get-jeff-data At this point, you should set the :envvar:`OPENMC_CROSS_SECTIONS` environment -variable to the absolute path of the file -``openmc/data/jeff-3.2-hdf5/cross_sections.xml``. +variable to the absolute path of the file ``jeff-3.2-hdf5/cross_sections.xml``. Using Cross Sections from MCNP ------------------------------ @@ -441,8 +469,7 @@ format, run the following: .. code-block:: sh - cd openmc/data - python convert_mcnp_endf70.py /path/to/mcnpdata/ + openmc-convert-mcnp70-data /path/to/mcnpdata/ where ``/path/to/mcnpdata`` is the directory containing the ``endf70[a-k]`` files. @@ -452,8 +479,7 @@ the following script: .. code-block:: sh - cd openmc/data - python convert_mcnp_endf71.py /path/to/mcnpdata + openmc-convert-mcnp71-data /path/to/mcnpdata where ``/path/to/mcnpdata`` is the directory containing the ``endf71x`` and ``ENDF71SaB`` directories. @@ -470,16 +496,16 @@ that are to be converted: 1. List each ACE library as a positional argument. This is very useful in conjunction with the usual shell utilities (ls, find, etc.). -2. Use the --xml option to specify a pre-v0.9 cross_sections.xml file. -3. Use the --xsdir option to specify a MCNP xsdir file. -4. Use the --xsdata option to specify a Serpent xsdata file. +2. Use the ``--xml`` option to specify a pre-v0.9 cross_sections.xml file. +3. Use the ``--xsdir` option to specify a MCNP xsdir file. +4. Use the ``--xsdata`` option to specify a Serpent xsdata file. The script does not use any extra information from cross_sections.xml/ xsdir/ xsdata files to determine whether the nuclide is metastable. Instead, the ---metastable argument can be used to specify whether the ZAID naming convention -follows the NNDC data convention (1000*Z + A + 300 + 100*m), or the MCNP data -convention (essentially the same as NNDC, except that the first metastable state -of Am242 is 95242 and the ground state is 95642). +``--metastable`` argument can be used to specify whether the ZAID naming +convention follows the NNDC data convention (1000*Z + A + 300 + 100*m), or the +MCNP data convention (essentially the same as NNDC, except that the first +metastable state of Am242 is 95242 and the ground state is 95642). The ``openmc-ace-to-hdf5`` script has the following command-line flags: diff --git a/openmc/arithmetic.py b/openmc/arithmetic.py index 1632520c5..f54953720 100644 --- a/openmc/arithmetic.py +++ b/openmc/arithmetic.py @@ -2,14 +2,13 @@ import sys import copy from collections import Iterable +from six import string_types import numpy as np import openmc from openmc.filter import _FILTER_TYPES import openmc.checkvalue as cv -if sys.version_info[0] >= 3: - basestring = str # Acceptable tally arithmetic binary operations _TALLY_ARITHMETIC_OPS = ['+', '-', '*', '/', '^'] @@ -86,18 +85,18 @@ class CrossScore(object): @left_score.setter def left_score(self, left_score): cv.check_type('left_score', left_score, - (basestring, CrossScore, AggregateScore)) + string_types + (CrossScore, AggregateScore)) self._left_score = left_score @right_score.setter def right_score(self, right_score): cv.check_type('right_score', right_score, - (basestring, CrossScore, AggregateScore)) + string_types + (CrossScore, AggregateScore)) self._right_score = right_score @binary_op.setter def binary_op(self, binary_op): - cv.check_type('binary_op', binary_op, basestring) + cv.check_type('binary_op', binary_op, string_types) cv.check_value('binary_op', binary_op, _TALLY_ARITHMETIC_OPS) self._binary_op = binary_op @@ -202,7 +201,7 @@ class CrossNuclide(object): @binary_op.setter def binary_op(self, binary_op): - cv.check_type('binary_op', binary_op, basestring) + cv.check_type('binary_op', binary_op, string_types) cv.check_value('binary_op', binary_op, _TALLY_ARITHMETIC_OPS) self._binary_op = binary_op @@ -343,7 +342,7 @@ class CrossFilter(object): @binary_op.setter def binary_op(self, binary_op): - cv.check_type('binary_op', binary_op, basestring) + cv.check_type('binary_op', binary_op, string_types) cv.check_value('binary_op', binary_op, _TALLY_ARITHMETIC_OPS) self._binary_op = binary_op @@ -495,12 +494,12 @@ class AggregateScore(object): @scores.setter def scores(self, scores): - cv.check_iterable_type('scores', scores, basestring) + cv.check_iterable_type('scores', scores, string_types) self._scores = scores @aggregate_op.setter def aggregate_op(self, aggregate_op): - cv.check_type('aggregate_op', aggregate_op, (basestring, CrossScore)) + cv.check_type('aggregate_op', aggregate_op, string_types +(CrossScore,)) cv.check_value('aggregate_op', aggregate_op, _TALLY_AGGREGATE_OPS) self._aggregate_op = aggregate_op @@ -575,12 +574,12 @@ class AggregateNuclide(object): @nuclides.setter def nuclides(self, nuclides): cv.check_iterable_type('nuclides', nuclides, - (basestring, openmc.Nuclide, CrossNuclide)) + string_types + (openmc.Nuclide, CrossNuclide)) self._nuclides = nuclides @aggregate_op.setter def aggregate_op(self, aggregate_op): - cv.check_type('aggregate_op', aggregate_op, basestring) + cv.check_type('aggregate_op', aggregate_op, string_types) cv.check_value('aggregate_op', aggregate_op, _TALLY_AGGREGATE_OPS) self._aggregate_op = aggregate_op @@ -711,7 +710,7 @@ class AggregateFilter(object): @aggregate_op.setter def aggregate_op(self, aggregate_op): - cv.check_type('aggregate_op', aggregate_op, basestring) + cv.check_type('aggregate_op', aggregate_op, string_types) cv.check_value('aggregate_op', aggregate_op, _TALLY_AGGREGATE_OPS) self._aggregate_op = aggregate_op diff --git a/openmc/cell.py b/openmc/cell.py index 1cfc09f37..f950963d2 100644 --- a/openmc/cell.py +++ b/openmc/cell.py @@ -5,6 +5,7 @@ from xml.etree import ElementTree as ET import sys import warnings +from six import string_types import numpy as np import openmc @@ -12,9 +13,6 @@ import openmc.checkvalue as cv from openmc.surface import Halfspace from openmc.region import Region, Intersection, Complement -if sys.version_info[0] >= 3: - basestring = str - # A static variable for auto-generated Cell IDs AUTO_CELL_ID = 10000 @@ -243,7 +241,7 @@ class Cell(object): @name.setter def name(self, name): if name is not None: - cv.check_type('cell name', name, basestring) + cv.check_type('cell name', name, string_types) self._name = name else: self._name = '' @@ -251,7 +249,7 @@ class Cell(object): @fill.setter def fill(self, fill): if fill is not None: - if isinstance(fill, basestring): + if isinstance(fill, string_types): if fill.strip().lower() != 'void': msg = 'Unable to set Cell ID="{0}" to use a non-Material ' \ 'or Universe fill "{1}"'.format(self._id, fill) @@ -336,7 +334,7 @@ class Cell(object): @distribcell_paths.setter def distribcell_paths(self, distribcell_paths): cv.check_iterable_type('distribcell_paths', distribcell_paths, - basestring) + string_types) self._distribcell_paths = distribcell_paths def add_surface(self, surface, halfspace): diff --git a/openmc/cmfd.py b/openmc/cmfd.py index 76d8685ff..51acf4d42 100644 --- a/openmc/cmfd.py +++ b/openmc/cmfd.py @@ -15,13 +15,12 @@ from numbers import Real, Integral from xml.etree import ElementTree as ET import sys +from six import string_types + from openmc.clean_xml import clean_xml_indentation from openmc.checkvalue import (check_type, check_length, check_value, check_greater_than, check_less_than) -if sys.version_info[0] >= 3: - basestring = str - class CMFDMesh(object): """A structured Cartesian mesh used for Coarse Mesh Finite Difference (CMFD) @@ -339,7 +338,7 @@ class CMFD(object): @display.setter def display(self, display): - check_type('CMFD display', display, basestring) + check_type('CMFD display', display, string_types) check_value('CMFD display', display, ['balance', 'dominance', 'entropy', 'source']) self._display = display diff --git a/openmc/data/ace.py b/openmc/data/ace.py index 831e40fc8..d7ec97edc 100644 --- a/openmc/data/ace.py +++ b/openmc/data/ace.py @@ -20,15 +20,12 @@ from os import SEEK_CUR import struct import sys +from six import string_types import numpy as np from openmc.mixin import EqualityMixin -if sys.version_info[0] >= 3: - basestring = str - - def ascii_to_binary(ascii_file, binary_file): """Convert an ACE file in ASCII format (type 1) to binary format (type 2). @@ -156,7 +153,7 @@ class Library(EqualityMixin): """ def __init__(self, filename, table_names=None, verbose=False): - if isinstance(table_names, basestring): + if isinstance(table_names, string_types): table_names = [table_names] if table_names is not None: table_names = set(table_names) diff --git a/openmc/data/angle_energy.py b/openmc/data/angle_energy.py index 9cee89aa5..8bf95152a 100644 --- a/openmc/data/angle_energy.py +++ b/openmc/data/angle_energy.py @@ -1,15 +1,15 @@ from abc import ABCMeta, abstractmethod from io import StringIO +from six import add_metaclass + import openmc.data from openmc.mixin import EqualityMixin +@add_metaclass(ABCMeta) class AngleEnergy(EqualityMixin): """Distribution in angle and energy of a secondary particle.""" - - __metaclass = ABCMeta - @abstractmethod def to_hdf5(self, group): pass diff --git a/openmc/data/energy_distribution.py b/openmc/data/energy_distribution.py index b42887b2f..c1762d5bc 100644 --- a/openmc/data/energy_distribution.py +++ b/openmc/data/energy_distribution.py @@ -3,6 +3,7 @@ from collections import Iterable from numbers import Integral, Real from warnings import warn +from six import add_metaclass import numpy as np from .function import Tabulated1D, INTERPOLATION_SCHEME @@ -12,11 +13,9 @@ from openmc.mixin import EqualityMixin from .endf import get_tab1_record, get_tab2_record +@add_metaclass(ABCMeta) class EnergyDistribution(EqualityMixin): """Abstract superclass for all energy distributions.""" - - __metaclass__ = ABCMeta - def __init__(self): pass diff --git a/data/fission_Q_data_endfb71.h5 b/openmc/data/fission_Q_data_endfb71.h5 similarity index 100% rename from data/fission_Q_data_endfb71.h5 rename to openmc/data/fission_Q_data_endfb71.h5 diff --git a/openmc/data/fission_energy.py b/openmc/data/fission_energy.py index 924fe0086..1746d62c8 100644 --- a/openmc/data/fission_energy.py +++ b/openmc/data/fission_energy.py @@ -12,9 +12,6 @@ from .function import Function1D, Tabulated1D, Polynomial, Sum import openmc.checkvalue as cv from openmc.mixin import EqualityMixin -if sys.version_info[0] >= 3: - basestring = str - def _extract_458_data(ev, units='eV'): """Read an ENDF file and extract the MF=1, MT=458 values. diff --git a/openmc/data/function.py b/openmc/data/function.py index 4121918e2..ed338f803 100644 --- a/openmc/data/function.py +++ b/openmc/data/function.py @@ -2,6 +2,7 @@ from abc import ABCMeta, abstractmethod from collections import Iterable, Callable from numbers import Real, Integral +from six import add_metaclass import numpy as np import openmc.data @@ -12,11 +13,9 @@ INTERPOLATION_SCHEME = {1: 'histogram', 2: 'linear-linear', 3: 'linear-log', 4: 'log-linear', 5: 'log-log'} +@add_metaclass(ABCMeta) class Function1D(EqualityMixin): """A function of one independent variable with HDF5 support.""" - - __metaclass__ = ABCMeta - @abstractmethod def __call__(self): pass diff --git a/openmc/data/neutron.py b/openmc/data/neutron.py index c125e3e04..4ce560860 100644 --- a/openmc/data/neutron.py +++ b/openmc/data/neutron.py @@ -5,6 +5,7 @@ from itertools import chain from numbers import Integral, Real from warnings import warn +from six import string_types import numpy as np import h5py @@ -20,9 +21,6 @@ from .urr import ProbabilityTables import openmc.checkvalue as cv from openmc.mixin import EqualityMixin -if sys.version_info[0] >= 3: - basestring = str - def _get_metadata(zaid, metastable_scheme='nndc'): """Return basic identifying data for a nuclide with a given ZAID. @@ -235,7 +233,7 @@ class IncidentNeutron(EqualityMixin): @name.setter def name(self, name): - cv.check_type('name', name, basestring) + cv.check_type('name', name, string_types) self._name = name @property @@ -291,7 +289,7 @@ class IncidentNeutron(EqualityMixin): def urr(self, urr): cv.check_type('probability table dictionary', urr, MutableMapping) for key, value in urr: - cv.check_type('probability table temperature', key, basestring) + cv.check_type('probability table temperature', key, string_types) cv.check_type('probability tables', value, ProbabilityTables) self._urr = urr diff --git a/openmc/data/product.py b/openmc/data/product.py index d9c3506e5..bcffec0da 100644 --- a/openmc/data/product.py +++ b/openmc/data/product.py @@ -3,6 +3,7 @@ from io import StringIO from numbers import Real import sys +from six import string_types import numpy as np import openmc.checkvalue as cv @@ -10,9 +11,6 @@ from openmc.mixin import EqualityMixin from .angle_energy import AngleEnergy from .function import Tabulated1D, Polynomial, Function1D -if sys.version_info[0] >= 3: - basestring = str - class Product(EqualityMixin): """Secondary particle emitted in a nuclear reaction @@ -115,7 +113,7 @@ class Product(EqualityMixin): @particle.setter def particle(self, particle): - cv.check_type('product particle type', particle, basestring) + cv.check_type('product particle type', particle, string_types) self._particle = particle @yield_.setter diff --git a/openmc/data/reaction.py b/openmc/data/reaction.py index 922e13ed4..c724474c9 100644 --- a/openmc/data/reaction.py +++ b/openmc/data/reaction.py @@ -5,6 +5,7 @@ from numbers import Real, Integral from warnings import warn from io import StringIO +from six import string_types import numpy as np import openmc.checkvalue as cv @@ -769,7 +770,7 @@ class Reaction(EqualityMixin): def xs(self, xs): cv.check_type('reaction cross section dictionary', xs, MutableMapping) for key, value in xs.items(): - cv.check_type('reaction cross section temperature', key, basestring) + cv.check_type('reaction cross section temperature', key, string_types) cv.check_type('reaction cross section', value, Callable) self._xs = xs diff --git a/openmc/element.py b/openmc/element.py index 1b1680614..e1484198c 100644 --- a/openmc/element.py +++ b/openmc/element.py @@ -1,14 +1,12 @@ import re import sys +from six import string_types + import openmc from openmc.checkvalue import check_type, check_length from openmc.data import NATURAL_ABUNDANCE -if sys.version_info[0] >= 3: - basestring = str - - class Element(object): """A natural element used in a material via . Internally, OpenMC will @@ -43,7 +41,7 @@ class Element(object): return False else: return True - elif isinstance(other, basestring) and other == self.name: + elif isinstance(other, string_types) and other == self.name: return True else: return False @@ -78,7 +76,7 @@ class Element(object): @name.setter def name(self, name): - check_type('element name', name, basestring) + check_type('element name', name, string_types) check_length('element name', name, 1, 2) self._name = name diff --git a/openmc/executor.py b/openmc/executor.py index fbd9e5d82..a20437e1c 100644 --- a/openmc/executor.py +++ b/openmc/executor.py @@ -3,8 +3,7 @@ import subprocess from numbers import Integral import sys -if sys.version_info[0] >= 3: - basestring = str +from six import string_types def _run(command, output, cwd): @@ -89,7 +88,7 @@ def run(particles=None, threads=None, geometry_debug=False, if geometry_debug: post_args += '-g ' - if isinstance(restart_file, basestring): + if isinstance(restart_file, string_types): post_args += '-r {0} '.format(restart_file) if tracks: diff --git a/openmc/filter.py b/openmc/filter.py index d11af96f5..72a7db47a 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1,21 +1,17 @@ from abc import ABCMeta, abstractproperty from collections import Iterable, OrderedDict import copy -from six import with_metaclass from numbers import Real, Integral import sys from xml.etree import ElementTree as ET +from six import add_metaclass import numpy as np import openmc import openmc.checkvalue as cv -if sys.version_info[0] >= 3: - basestring = str - - _FILTER_TYPES = ['universe', 'material', 'cell', 'cellborn', 'surface', 'mesh', 'energy', 'energyout', 'mu', 'polar', 'azimuthal', 'distribcell', 'delayedgroup'] @@ -37,7 +33,8 @@ class FilterMeta(ABCMeta): **kwargs) -class Filter(with_metaclass(FilterMeta, object)): +@add_metaclass(FilterMeta) +class Filter(object): """Tally modifier that describes phase-space and other characteristics. Parameters diff --git a/openmc/lattice.py b/openmc/lattice.py index c6a5af410..95c16841f 100644 --- a/openmc/lattice.py +++ b/openmc/lattice.py @@ -1,21 +1,20 @@ from __future__ import division -import abc +from abc import ABCMeta from collections import OrderedDict, Iterable from math import sqrt, floor from numbers import Real, Integral from xml.etree import ElementTree as ET import sys +from six import add_metaclass, string_types import numpy as np import openmc.checkvalue as cv import openmc -if sys.version_info[0] >= 3: - basestring = str - +@add_metaclass(ABCMeta) class Lattice(object): """A repeating structure wherein each element is a universe. @@ -42,10 +41,6 @@ class Lattice(object): of the lattice """ - - # This is an abstract class which cannot be instantiated - __metaclass__ = abc.ABCMeta - def __init__(self, lattice_id=None, name=''): # Initialize Lattice class attributes self.id = lattice_id @@ -106,7 +101,7 @@ class Lattice(object): @name.setter def name(self, name): if name is not None: - cv.check_type('lattice name', name, basestring) + cv.check_type('lattice name', name, string_types) self._name = name else: self._name = '' diff --git a/openmc/macroscopic.py b/openmc/macroscopic.py index a1ca62c9a..4d3589141 100644 --- a/openmc/macroscopic.py +++ b/openmc/macroscopic.py @@ -1,9 +1,8 @@ import sys -from openmc.checkvalue import check_type +from six import string_types -if sys.version_info[0] >= 3: - basestring = str +from openmc.checkvalue import check_type class Macroscopic(object): @@ -34,7 +33,7 @@ class Macroscopic(object): return False else: return True - elif isinstance(other, basestring) and other == self.name: + elif isinstance(other, string_types) and other == self.name: return True else: return False @@ -55,5 +54,5 @@ class Macroscopic(object): @name.setter def name(self, name): - check_type('name', name, basestring) + check_type('name', name, string_types) self._name = name diff --git a/openmc/material.py b/openmc/material.py index 0639db562..6f9c4ba15 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -5,14 +5,13 @@ import warnings from xml.etree import ElementTree as ET import sys +from six import string_types + import openmc import openmc.data import openmc.checkvalue as cv from openmc.clean_xml import sort_xml_elements, clean_xml_indentation -if sys.version_info[0] >= 3: - basestring = str - # A static variable for auto-generated Material IDs AUTO_MATERIAL_ID = 10000 @@ -207,7 +206,7 @@ class Material(object): def name(self, name): if name is not None: cv.check_type('name for Material ID="{0}"'.format(self._id), - name, basestring) + name, string_types) self._name = name else: self._name = '' @@ -256,7 +255,7 @@ class Material(object): warnings.warn('This feature is not yet implemented in a release ' 'version of openmc') - if not isinstance(filename, basestring) and filename is not None: + if not isinstance(filename, string_types) and filename is not None: msg = 'Unable to add OTF material file to Material ID="{0}" with a ' \ 'non-string name "{1}"'.format(self._id, filename) raise ValueError(msg) @@ -290,7 +289,7 @@ class Material(object): 'macroscopic data-set has already been added'.format(self._id) raise ValueError(msg) - if not isinstance(nuclide, (openmc.Nuclide, basestring)): + if not isinstance(nuclide, string_types + (openmc.Nuclide,)): msg = 'Unable to add a Nuclide to Material ID="{0}" with a ' \ 'non-Nuclide value "{1}"'.format(self._id, nuclide) raise ValueError(msg) @@ -355,7 +354,7 @@ class Material(object): 'has already been added'.format(self._id, macroscopic) raise ValueError(msg) - if not isinstance(macroscopic, (openmc.Macroscopic, basestring)): + if not isinstance(macroscopic, string_types + (openmc.Macroscopic,)): msg = 'Unable to add a Macroscopic to Material ID="{0}" with a ' \ 'non-Macroscopic value "{1}"'.format(self._id, macroscopic) raise ValueError(msg) @@ -425,7 +424,7 @@ class Material(object): 'macroscopic data-set has already been added'.format(self._id) raise ValueError(msg) - if not isinstance(element, (openmc.Element, basestring)): + if not isinstance(element, string_types + (openmc.Element,)): msg = 'Unable to add an Element to Material ID="{0}" with a ' \ 'non-Element value "{1}"'.format(self._id, element) raise ValueError(msg) @@ -490,7 +489,7 @@ class Material(object): 'macroscopic data-set has already been added'.format(self._id) raise ValueError(msg) - if not isinstance(name, basestring): + if not isinstance(name, string_types): msg = 'Unable to add an S(a,b) table to Material ID="{0}" with a ' \ 'non-string table name "{1}"'.format(self._id, name) raise ValueError(msg) diff --git a/openmc/mesh.py b/openmc/mesh.py index 21144469f..d626d728a 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -3,15 +3,13 @@ from numbers import Real, Integral from xml.etree import ElementTree as ET import sys +from six import string_types import numpy as np import openmc.checkvalue as cv import openmc -if sys.version_info[0] >= 3: - basestring = str - # "Static" variable for auto-generated and Mesh IDs AUTO_MESH_ID = 10000 @@ -131,7 +129,7 @@ class Mesh(object): def name(self, name): if name is not None: cv.check_type('name for mesh ID="{0}"'.format(self._id), - name, basestring) + name, string_types) self._name = name else: self._name = '' @@ -139,7 +137,7 @@ class Mesh(object): @type.setter def type(self, meshtype): cv.check_type('type for mesh ID="{0}"'.format(self._id), - meshtype, basestring) + meshtype, string_types) cv.check_value('type for mesh ID="{0}"'.format(self._id), meshtype, ['regular']) self._type = meshtype diff --git a/openmc/mgxs/groups.py b/openmc/mgxs/groups.py index 068977d88..9441a8051 100644 --- a/openmc/mgxs/groups.py +++ b/openmc/mgxs/groups.py @@ -8,10 +8,6 @@ import numpy as np import openmc.checkvalue as cv -if sys.version_info[0] >= 3: - basestring = str - - class EnergyGroups(object): """An energy groups structure used for multi-group cross-sections. diff --git a/openmc/mgxs/library.py b/openmc/mgxs/library.py index cab7b4dce..08e0bb404 100644 --- a/openmc/mgxs/library.py +++ b/openmc/mgxs/library.py @@ -6,6 +6,7 @@ from numbers import Integral from collections import OrderedDict from warnings import warn +from six import string_types import numpy as np import openmc @@ -14,10 +15,6 @@ import openmc.checkvalue as cv from openmc.tallies import ESTIMATOR_TYPES -if sys.version_info[0] >= 3: - basestring = str - - class Library(object): """A multi-energy-group and multi-delayed-group cross section library for some energy group structure. @@ -66,8 +63,8 @@ class Library(object): The highest legendre moment in the scattering matrices (default is 0) energy_groups : openmc.mgxs.EnergyGroups Energy group structure for energy condensation - delayed_groups : list of int - Delayed groups to filter out the xs + num_delayed_groups : int + Number of delayed groups estimator : str or None The tally estimator used to compute multi-group cross sections. If None, the default for each MGXS type is used. @@ -102,7 +99,7 @@ class Library(object): self._domain_type = None self._domains = 'all' self._energy_groups = None - self._delayed_groups = None + self._num_delayed_groups = 0 self._correction = 'P0' self._legendre_order = 0 self._tally_trigger = None @@ -135,7 +132,7 @@ class Library(object): clone._correction = self.correction clone._legendre_order = self.legendre_order clone._energy_groups = copy.deepcopy(self.energy_groups, memo) - clone._delayed_groups = copy.deepcopy(self.delayed_groups, memo) + clone._num_delayed_groups = self.num_delayed_groups clone._tally_trigger = copy.deepcopy(self.tally_trigger, memo) clone._all_mgxs = copy.deepcopy(self.all_mgxs) clone._sp_filename = self._sp_filename @@ -205,8 +202,8 @@ class Library(object): return self._energy_groups @property - def delayed_groups(self): - return self._delayed_groups + def num_delayed_groups(self): + return self._num_delayed_groups @property def correction(self): @@ -228,13 +225,6 @@ class Library(object): def num_groups(self): return self.energy_groups.num_groups - @property - def num_delayed_groups(self): - if self.delayed_groups == None: - return 0 - else: - return len(self.delayed_groups) - @property def all_mgxs(self): return self._all_mgxs @@ -259,7 +249,7 @@ class Library(object): @name.setter def name(self, name): - cv.check_type('name', name, basestring) + cv.check_type('name', name, string_types) self._name = name @mgxs_types.setter @@ -268,7 +258,7 @@ class Library(object): if mgxs_types == 'all': self._mgxs_types = all_mgxs_types else: - cv.check_iterable_type('mgxs_types', mgxs_types, basestring) + cv.check_iterable_type('mgxs_types', mgxs_types, string_types) for mgxs_type in mgxs_types: cv.check_value('mgxs_type', mgxs_type, all_mgxs_types) self._mgxs_types = mgxs_types @@ -334,22 +324,14 @@ class Library(object): cv.check_type('energy groups', energy_groups, openmc.mgxs.EnergyGroups) self._energy_groups = energy_groups - @delayed_groups.setter - def delayed_groups(self, delayed_groups): + @num_delayed_groups.setter + def num_delayed_groups(self, num_delayed_groups): - if delayed_groups != None: - - cv.check_type('delayed groups', delayed_groups, list, int) - cv.check_greater_than('num delayed groups', len(delayed_groups), 0) - - # Check that the groups are within [1, MAX_DELAYED_GROUPS] - for group in delayed_groups: - cv.check_greater_than('delayed group', group, 0) - cv.check_less_than('delayed group', group, - openmc.mgxs.MAX_DELAYED_GROUPS, - equality=True) - - self._delayed_groups = delayed_groups + cv.check_less_than('num delayed groups', num_delayed_groups, + openmc.mgxs.MAX_DELAYED_GROUPS, equality=True) + cv.check_greater_than('num delayed groups', num_delayed_groups, 0, + equality=True) + self._num_delayed_groups = num_delayed_groups @correction.setter def correction(self, correction): @@ -434,7 +416,12 @@ class Library(object): mgxs.estimator = self.estimator if mgxs_type in openmc.mgxs.MDGXS_TYPES: - mgxs.delayed_groups = self.delayed_groups + if self.num_delayed_groups == 0: + mgxs.delayed_groups = None + else: + delayed_groups \ + = list(range(1,self.num_delayed_groups+1)) + mgxs.delayed_groups = delayed_groups # If a tally trigger was specified, add it to the MGXS if self.tally_trigger is not None: @@ -730,8 +717,8 @@ class Library(object): 'since a statepoint has not yet been loaded' raise ValueError(msg) - cv.check_type('filename', filename, basestring) - cv.check_type('directory', directory, basestring) + cv.check_type('filename', filename, string_types) + cv.check_type('directory', directory, string_types) import h5py @@ -773,8 +760,8 @@ class Library(object): """ - cv.check_type('filename', filename, basestring) - cv.check_type('directory', directory, basestring) + cv.check_type('filename', filename, string_types) + cv.check_type('directory', directory, string_types) # Make directory if it does not exist if not os.path.exists(directory): @@ -808,8 +795,8 @@ class Library(object): """ - cv.check_type('filename', filename, basestring) - cv.check_type('directory', directory, basestring) + cv.check_type('filename', filename, string_types) + cv.check_type('directory', directory, string_types) # Make directory if it does not exist if not os.path.exists(directory): @@ -873,8 +860,8 @@ class Library(object): cv.check_type('domain', domain, (openmc.Material, openmc.Cell, openmc.Universe, openmc.Mesh)) - cv.check_type('xsdata_name', xsdata_name, basestring) - cv.check_type('nuclide', nuclide, basestring) + cv.check_type('xsdata_name', xsdata_name, string_types) + cv.check_type('nuclide', nuclide, string_types) cv.check_value('xs_type', xs_type, ['macro', 'micro']) cv.check_type('order', order, (type(None), Integral)) if order is not None: @@ -899,7 +886,7 @@ class Library(object): if nuclide != 'total': name += '_' + nuclide xsdata = openmc.XSdata(name, self.energy_groups) - xsdata.delayed_groups = self.num_delayed_groups + xsdata.num_delayed_groups = self.num_delayed_groups if order is None: # Set the order to the Library's order (the defualt behavior) @@ -1100,7 +1087,7 @@ class Library(object): cv.check_value('xs_type', xs_type, ['macro', 'micro']) if xsdata_names is not None: - cv.check_iterable_type('xsdata_names', xsdata_names, basestring) + cv.check_iterable_type('xsdata_names', xsdata_names, string_types) # If gathering material-specific data, set the xs_type to macro if not self.by_nuclide: @@ -1108,7 +1095,8 @@ class Library(object): # Initialize file mgxs_file = openmc.MGXSLibrary(self.energy_groups, - delayed_groups=self.num_delayed_groups) + num_delayed_groups=\ + self.num_delayed_groups) if self.domain_type == 'mesh': # Create the xsdata objects and add to the mgxs_file diff --git a/openmc/mgxs/mdgxs.py b/openmc/mgxs/mdgxs.py index dc0d47833..a5ccd8da6 100644 --- a/openmc/mgxs/mdgxs.py +++ b/openmc/mgxs/mdgxs.py @@ -6,8 +6,9 @@ import warnings import os import sys import copy -import abc +from abc import ABCMeta +from six import add_metaclass, string_types import numpy as np import openmc @@ -15,8 +16,6 @@ from openmc.mgxs import MGXS from openmc.mgxs.mgxs import _DOMAIN_TO_FILTER import openmc.checkvalue as cv -if sys.version_info[0] >= 3: - basestring = str # Supported cross section types MDGXS_TYPES = ['delayed-nu-fission', @@ -29,6 +28,7 @@ MDGXS_TYPES = ['delayed-nu-fission', MAX_DELAYED_GROUPS = 8 +@add_metaclass(ABCMeta) class MDGXS(MGXS): """An abstract multi-delayed-group cross section for some energy and delayed group structures within some spatial domain. @@ -118,10 +118,6 @@ class MDGXS(MGXS): The key used to index multi-group cross sections in an HDF5 data store """ - - # This is an abstract class which cannot be instantiated - __metaclass__ = abc.ABCMeta - def __init__(self, domain=None, domain_type=None, energy_groups=None, delayed_groups=None, by_nuclide=False, name=''): super(MDGXS, self).__init__(domain, domain_type, energy_groups, @@ -189,7 +185,7 @@ class MDGXS(MGXS): cv.check_less_than('delayed group', group, MAX_DELAYED_GROUPS, equality=True) - self._delayed_groups = delayed_groups + self._delayed_groups = delayed_groups @property def filters(self): @@ -326,7 +322,7 @@ class MDGXS(MGXS): filter_bins = [] # Construct a collection of the domain filter bins - if not isinstance(subdomains, basestring): + if not isinstance(subdomains, string_types): cv.check_iterable_type('subdomains', subdomains, Integral, max_depth=3) for subdomain in subdomains: @@ -334,7 +330,7 @@ class MDGXS(MGXS): filter_bins.append((subdomain,)) # Construct list of energy group bounds tuples for all requested groups - if not isinstance(groups, basestring): + if not isinstance(groups, string_types): cv.check_iterable_type('groups', groups, Integral) for group in groups: filters.append(openmc.EnergyFilter) @@ -342,7 +338,7 @@ class MDGXS(MGXS): (self.energy_groups.get_group_bounds(group),)) # Construct list of delayed group tuples for all requested groups - if not isinstance(delayed_groups, basestring): + if not isinstance(delayed_groups, string_types): cv.check_type('delayed groups', delayed_groups, list, int) for delayed_group in delayed_groups: filters.append(openmc.DelayedGroupFilter) @@ -438,7 +434,7 @@ class MDGXS(MGXS): """ - cv.check_iterable_type('nuclides', nuclides, basestring) + cv.check_iterable_type('nuclides', nuclides, string_types) cv.check_iterable_type('energy_groups', groups, Integral) cv.check_type('delayed groups', delayed_groups, list, int) @@ -548,7 +544,7 @@ class MDGXS(MGXS): return # Construct a collection of the subdomains to report - if not isinstance(subdomains, basestring): + if not isinstance(subdomains, string_types): cv.check_iterable_type('subdomains', subdomains, Integral) elif self.domain_type == 'distribcell': subdomains = np.arange(self.num_subdomains, dtype=np.int) @@ -565,7 +561,7 @@ class MDGXS(MGXS): elif nuclides == 'sum': nuclides = ['sum'] else: - cv.check_iterable_type('nuclides', nuclides, basestring) + cv.check_iterable_type('nuclides', nuclides, string_types) else: nuclides = ['sum'] @@ -655,8 +651,8 @@ class MDGXS(MGXS): """ - cv.check_type('filename', filename, basestring) - cv.check_type('directory', directory, basestring) + cv.check_type('filename', filename, string_types) + cv.check_type('directory', directory, string_types) cv.check_value('format', format, ['csv', 'excel', 'pickle', 'latex']) cv.check_value('xs_type', xs_type, ['macro', 'micro']) @@ -746,11 +742,11 @@ class MDGXS(MGXS): """ - if not isinstance(groups, basestring): + if not isinstance(groups, string_types): cv.check_iterable_type('groups', groups, Integral) if nuclides != 'all' and nuclides != 'sum': - cv.check_iterable_type('nuclides', nuclides, basestring) - if not isinstance(delayed_groups, basestring): + cv.check_iterable_type('nuclides', nuclides, string_types) + if not isinstance(delayed_groups, string_types): cv.check_type('delayed groups', delayed_groups, list, int) cv.check_value('xs_type', xs_type, ['macro', 'micro']) @@ -825,7 +821,7 @@ class MDGXS(MGXS): columns = ['group in'] # Select out those groups the user requested - if not isinstance(groups, basestring): + if not isinstance(groups, string_types): if 'group in' in df: df = df[df['group in'].isin(groups)] if 'group out' in df: @@ -1216,7 +1212,7 @@ class ChiDelayed(MDGXS): filter_bins = [] # Construct a collection of the domain filter bins - if not isinstance(subdomains, basestring): + if not isinstance(subdomains, string_types): cv.check_iterable_type('subdomains', subdomains, Integral, max_depth=3) for subdomain in subdomains: @@ -1224,7 +1220,7 @@ class ChiDelayed(MDGXS): filter_bins.append((subdomain,)) # Construct list of energy group bounds tuples for all requested groups - if not isinstance(groups, basestring): + if not isinstance(groups, string_types): cv.check_iterable_type('groups', groups, Integral) for group in groups: filters.append(openmc.EnergyoutFilter) @@ -1232,7 +1228,7 @@ class ChiDelayed(MDGXS): (self.energy_groups.get_group_bounds(group),)) # Construct list of delayed group tuples for all requested groups - if not isinstance(delayed_groups, basestring): + if not isinstance(delayed_groups, string_types): cv.check_type('delayed groups', delayed_groups, list, int) for delayed_group in delayed_groups: filters.append(openmc.DelayedGroupFilter) @@ -1280,7 +1276,7 @@ class ChiDelayed(MDGXS): # Get chi delayed for user-specified nuclides in the domain else: - cv.check_iterable_type('nuclides', nuclides, basestring) + cv.check_iterable_type('nuclides', nuclides, string_types) xs = self.xs_tally.get_values(filters=filters, filter_bins=filter_bins, nuclides=nuclides, value=value) @@ -1472,6 +1468,11 @@ class Beta(MDGXS): \beta_{d,g} &= \frac{\langle \nu^d \sigma_f \phi \rangle} {\langle \nu \sigma_f \phi \rangle} + NOTE: The Beta MGXS is the delayed neutron fraction computed directly from + the nuclear data. Often the delayed neutron fraction is + "importance-weighted" by the adjoint flux and called "beta-effective". It + is important to make clear that this Beta is not importance-weighted. + Parameters ---------- domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index 5a305cf50..b638d1791 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -6,9 +6,10 @@ import warnings import os import sys import copy -import abc +from abc import ABCMeta import itertools +from six import add_metaclass, string_types import numpy as np import openmc @@ -16,9 +17,6 @@ import openmc.checkvalue as cv from openmc.tallies import ESTIMATOR_TYPES from openmc.mgxs import EnergyGroups -if sys.version_info[0] >= 3: - basestring = str - # Supported cross section types MGXS_TYPES = ['total', @@ -62,6 +60,7 @@ _DOMAINS = (openmc.Cell, openmc.Mesh) +@add_metaclass(ABCMeta) class MGXS(object): """An abstract multi-group cross section for some energy group structure within some spatial domain. @@ -146,10 +145,6 @@ class MGXS(object): The key used to index multi-group cross sections in an HDF5 data store """ - - # This is an abstract class which cannot be instantiated - __metaclass__ = abc.ABCMeta - def __init__(self, domain=None, domain_type=None, energy_groups=None, by_nuclide=False, name=''): self._name = '' @@ -369,7 +364,7 @@ class MGXS(object): @name.setter def name(self, name): - cv.check_type('name', name, basestring) + cv.check_type('name', name, string_types) self._name = name @by_nuclide.setter @@ -379,7 +374,7 @@ class MGXS(object): @nuclides.setter def nuclides(self, nuclides): - cv.check_iterable_type('nuclides', nuclides, basestring) + cv.check_iterable_type('nuclides', nuclides, string_types) self._nuclides = nuclides @estimator.setter @@ -565,7 +560,7 @@ class MGXS(object): """ - cv.check_type('nuclide', nuclide, basestring) + cv.check_type('nuclide', nuclide, string_types) # Get list of all nuclides in the spatial domain nuclides = self.domain.get_nuclide_densities() @@ -791,7 +786,7 @@ class MGXS(object): filter_bins = [] # Construct a collection of the domain filter bins - if not isinstance(subdomains, basestring): + if not isinstance(subdomains, string_types): cv.check_iterable_type('subdomains', subdomains, Integral, max_depth=3) for subdomain in subdomains: @@ -799,7 +794,7 @@ class MGXS(object): filter_bins.append((subdomain,)) # Construct list of energy group bounds tuples for all requested groups - if not isinstance(groups, basestring): + if not isinstance(groups, string_types): cv.check_iterable_type('groups', groups, Integral) for group in groups: filters.append(openmc.EnergyFilter) @@ -961,7 +956,7 @@ class MGXS(object): """ # Construct a collection of the subdomain filter bins to average across - if not isinstance(subdomains, basestring): + if not isinstance(subdomains, string_types): cv.check_iterable_type('subdomains', subdomains, Integral) elif self.domain_type == 'distribcell': subdomains = np.arange(self.num_subdomains) @@ -1016,7 +1011,7 @@ class MGXS(object): """ - cv.check_iterable_type('nuclides', nuclides, basestring) + cv.check_iterable_type('nuclides', nuclides, string_types) cv.check_iterable_type('energy_groups', groups, Integral) # Build lists of filters and filter bins to slice @@ -1170,7 +1165,7 @@ class MGXS(object): """ # Construct a collection of the subdomains to report - if not isinstance(subdomains, basestring): + if not isinstance(subdomains, string_types): cv.check_iterable_type('subdomains', subdomains, Integral) elif self.domain_type == 'distribcell': subdomains = np.arange(self.num_subdomains, dtype=np.int) @@ -1187,7 +1182,7 @@ class MGXS(object): elif nuclides == 'sum': nuclides = ['sum'] else: - cv.check_iterable_type('nuclides', nuclides, basestring) + cv.check_iterable_type('nuclides', nuclides, string_types) else: nuclides = ['sum'] @@ -1305,7 +1300,7 @@ class MGXS(object): xs_results = h5py.File(filename, 'w') # Construct a collection of the subdomains to report - if not isinstance(subdomains, basestring): + if not isinstance(subdomains, string_types): cv.check_iterable_type('subdomains', subdomains, Integral) elif self.domain_type == 'distribcell': subdomains = np.arange(self.num_subdomains, dtype=np.int) @@ -1326,7 +1321,7 @@ class MGXS(object): elif nuclides == 'sum': nuclides = ['sum'] else: - cv.check_iterable_type('nuclides', nuclides, basestring) + cv.check_iterable_type('nuclides', nuclides, string_types) else: nuclides = ['sum'] @@ -1404,8 +1399,8 @@ class MGXS(object): """ - cv.check_type('filename', filename, basestring) - cv.check_type('directory', directory, basestring) + cv.check_type('filename', filename, string_types) + cv.check_type('directory', directory, string_types) cv.check_value('format', format, ['csv', 'excel', 'pickle', 'latex']) cv.check_value('xs_type', xs_type, ['macro', 'micro']) @@ -1491,10 +1486,10 @@ class MGXS(object): """ - if not isinstance(groups, basestring): + if not isinstance(groups, string_types): cv.check_iterable_type('groups', groups, Integral) if nuclides != 'all' and nuclides != 'sum': - cv.check_iterable_type('nuclides', nuclides, basestring) + cv.check_iterable_type('nuclides', nuclides, string_types) cv.check_value('xs_type', xs_type, ['macro', 'micro']) # Get a Pandas DataFrame from the derived xs tally @@ -1566,7 +1561,7 @@ class MGXS(object): columns = ['group in'] # Select out those groups the user requested - if not isinstance(groups, basestring): + if not isinstance(groups, string_types): if 'group in' in df: df = df[df['group in'].isin(groups)] if 'group out' in df: @@ -1619,6 +1614,7 @@ class MGXS(object): return 'cm^-1' if xs_type == 'macro' else 'barns' +@add_metaclass(ABCMeta) class MatrixMGXS(MGXS): """An abstract multi-group cross section for some energy group structure within some spatial domain. This class is specifically intended for @@ -1706,10 +1702,6 @@ class MatrixMGXS(MGXS): The key used to index multi-group cross sections in an HDF5 data store """ - - # This is an abstract class which cannot be instantiated - __metaclass__ = abc.ABCMeta - @property def filters(self): # Create the non-domain specific Filters for the Tallies @@ -1789,7 +1781,7 @@ class MatrixMGXS(MGXS): filter_bins = [] # Construct a collection of the domain filter bins - if not isinstance(subdomains, basestring): + if not isinstance(subdomains, string_types): cv.check_iterable_type('subdomains', subdomains, Integral, max_depth=3) for subdomain in subdomains: @@ -1797,7 +1789,7 @@ class MatrixMGXS(MGXS): filter_bins.append((subdomain,)) # Construct list of energy group bounds tuples for all requested groups - if not isinstance(in_groups, basestring): + if not isinstance(in_groups, string_types): cv.check_iterable_type('groups', in_groups, Integral) for group in in_groups: filters.append(openmc.EnergyFilter) @@ -1805,7 +1797,7 @@ class MatrixMGXS(MGXS): self.energy_groups.get_group_bounds(group),)) # Construct list of energy group bounds tuples for all requested groups - if not isinstance(out_groups, basestring): + if not isinstance(out_groups, string_types): cv.check_iterable_type('groups', out_groups, Integral) for group in out_groups: filters.append(openmc.EnergyoutFilter) @@ -1951,7 +1943,7 @@ class MatrixMGXS(MGXS): """ # Construct a collection of the subdomains to report - if not isinstance(subdomains, basestring): + if not isinstance(subdomains, string_types): cv.check_iterable_type('subdomains', subdomains, Integral) elif self.domain_type == 'distribcell': subdomains = np.arange(self.num_subdomains, dtype=np.int) @@ -1968,7 +1960,7 @@ class MatrixMGXS(MGXS): if nuclides == 'sum': nuclides = ['sum'] else: - cv.check_iterable_type('nuclides', nuclides, basestring) + cv.check_iterable_type('nuclides', nuclides, string_types) else: nuclides = ['sum'] @@ -3624,21 +3616,21 @@ class ScatterMatrixXS(MatrixMGXS): filter_bins = [] # Construct a collection of the domain filter bins - if not isinstance(subdomains, basestring): + if not isinstance(subdomains, string_types): cv.check_iterable_type('subdomains', subdomains, Integral, max_depth=3) for subdomain in subdomains: filters.append(_DOMAIN_TO_FILTER[self.domain_type]) filter_bins.append((subdomain,)) # Construct list of energy group bounds tuples for all requested groups - if not isinstance(in_groups, basestring): + if not isinstance(in_groups, string_types): cv.check_iterable_type('groups', in_groups, Integral) for group in in_groups: filters.append(openmc.EnergyFilter) filter_bins.append((self.energy_groups.get_group_bounds(group),)) # Construct list of energy group bounds tuples for all requested groups - if not isinstance(out_groups, basestring): + if not isinstance(out_groups, string_types): cv.check_iterable_type('groups', out_groups, Integral) for group in out_groups: filters.append(openmc.EnergyoutFilter) @@ -3812,7 +3804,7 @@ class ScatterMatrixXS(MatrixMGXS): """ # Construct a collection of the subdomains to report - if not isinstance(subdomains, basestring): + if not isinstance(subdomains, string_types): cv.check_iterable_type('subdomains', subdomains, Integral) elif self.domain_type == 'distribcell': subdomains = np.arange(self.num_subdomains, dtype=np.int) @@ -3829,7 +3821,7 @@ class ScatterMatrixXS(MatrixMGXS): if nuclides == 'sum': nuclides = ['sum'] else: - cv.check_iterable_type('nuclides', nuclides, basestring) + cv.check_iterable_type('nuclides', nuclides, string_types) else: nuclides = ['sum'] @@ -4612,14 +4604,14 @@ class Chi(MGXS): filter_bins = [] # Construct a collection of the domain filter bins - if not isinstance(subdomains, basestring): + if not isinstance(subdomains, string_types): cv.check_iterable_type('subdomains', subdomains, Integral, max_depth=3) for subdomain in subdomains: filters.append(_DOMAIN_TO_FILTER[self.domain_type]) filter_bins.append((subdomain,)) # Construct list of energy group bounds tuples for all requested groups - if not isinstance(groups, basestring): + if not isinstance(groups, string_types): cv.check_iterable_type('groups', groups, Integral) for group in groups: filters.append(openmc.EnergyoutFilter) @@ -4664,7 +4656,7 @@ class Chi(MGXS): # Get chi for user-specified nuclides in the domain else: - cv.check_iterable_type('nuclides', nuclides, basestring) + cv.check_iterable_type('nuclides', nuclides, string_types) xs = self.xs_tally.get_values(filters=filters, filter_bins=filter_bins, nuclides=nuclides, value=value) diff --git a/openmc/mgxs_library.py b/openmc/mgxs_library.py index 2d9f94626..6f851e8f2 100644 --- a/openmc/mgxs_library.py +++ b/openmc/mgxs_library.py @@ -2,21 +2,21 @@ from collections import Iterable from numbers import Real, Integral import sys +from six import string_types import numpy as np import h5py import openmc import openmc.mgxs from openmc.checkvalue import check_type, check_value, check_greater_than, \ - check_iterable_type + check_iterable_type, check_less_than -if sys.version_info[0] >= 3: - basestring = str # Supported incoming particle MGXS angular treatment representations _REPRESENTATIONS = ['isotropic', 'angle'] _SCATTER_TYPES = ['tabular', 'legendre', 'histogram'] -_SCATTER_SHAPES = ["[Order][G][G']"] +_XS_SHAPES = ["[Order][G][G']", "[G]", "[G']", "[G][G']", "[DG]", "[DG][G]", + "[DG][G']", "[DG][G][G']"] class XSdata(object): @@ -35,7 +35,7 @@ class XSdata(object): temperatures : Iterable of float Temperatures (in units of Kelvin) of the provided datasets. Defaults to a single temperature at 294K. - delayed_groups : int + num_delayed_groups : int Number of delayed groups Attributes @@ -50,14 +50,12 @@ class XSdata(object): to a single temperature at 294K. energy_groups : openmc.mgxs.EnergyGroups Energy group structure - delayed_groups : int + num_delayed_groups : int Num delayed groups fissionable : bool Whether or not this is a fissionable data set. scatter_format : {'legendre', 'histogram', or 'tabular'} Angular distribution representation (legendre, histogram, or tabular) - scatter_shapes : {"[Order][G][G']"} - Dimensionality of the scattering and multiplicity matrices order : int Either the Legendre order, number of bins, or number of points used to describe the angular distribution associated with each group-to-group @@ -71,7 +69,8 @@ class XSdata(object): is "angle". num_polar : int Number of equal width angular bins that the polar angular domain is - subdivided into. This only applies when ``representation`` is "angle". + subdivided into. This only applies when :attr:`XSdata.representation` + is "angle". total : dict of numpy.ndarray Group-wise total cross section. absorption : dict of numpy.ndarray @@ -95,7 +94,7 @@ class XSdata(object): approximation that the fission spectra does not depend on incoming energy. If the user does not wish to make this approximation, then this should not be provided and this information included in the - ``nu_fission`` attribute instead. + :attr:`XSdata.nu_fission` attribute instead. chi_prompt : dict of numpy.ndarray Group-wise prompt fission spectra ordered by increasing group index (i.e., fast to thermal). This attribute should be used if chi from @@ -114,25 +113,58 @@ class XSdata(object): beta : dict of numpy.ndarray Delayed-group-wise delayed neutron fraction cross section vector. decay_rate : dict of numpy.ndarray - Delayed-group-wise decay rate cross section vector. + Delayed-group-wise decay rate vector. inverse_velocity : dict of numpy.ndarray Inverse of velocity, in units of sec/cm. + xs_shapes : dict of iterable of int + Dictionary with keys of _XS_SHAPES and iterable of int values with the + corresponding shapes where "Order" corresponds to the pn scattering + order, "G" corresponds to incoming energy group, "G'" corresponds to + outgoing energy group, and "DG" corresponds to delayed group. + + Notes + ----- + The parameters containing cross section data have dimensionalities which + depend upon the value of :attr:`XSdata.representation` as well as the + number of Legendre or other angular dimensions as described by + :attr:`XSdata.order`. The :attr:`XSdata.xs_shapes` are provided to obtain + the dimensionality of the data for each temperature. + + The following are cross sections which should use each of the properties. + Note that some cross sections can be input in more than one shape so they + are listed multiple times: + + [Order][G][G']: scatter_matrix + + [G]: total, absorption, fission, kappa_fission, nu_fission, + prompt_nu_fission, inverse_velocity + + [G']: chi, chi_prompt, chi_delayed + + [G][G']: multiplicity_matrix, nu_fission, prompt_nu_fission + + [DG]: beta, decay_rate + + [DG][G]: delayed_nu_fission, beta, decay_rate + + [DG][G']: chi_delayed + + [DG][G][G']: delayed_nu_fission """ def __init__(self, name, energy_groups, temperatures=[294.], - representation='isotropic', delayed_groups=0): + representation='isotropic', num_delayed_groups=0): # Initialize class attributes self.name = name self.energy_groups = energy_groups - self.delayed_groups = delayed_groups + self.num_delayed_groups = num_delayed_groups self.temperatures = temperatures self.representation = representation self._atomic_weight_ratio = None self._fissionable = False self._scatter_format = 'legendre' - self._scatter_shape = "[Order][G][G']" self._order = None self._num_polar = None self._num_azimuthal = None @@ -151,6 +183,7 @@ class XSdata(object): self._beta = len(temperatures) * [None] self._decay_rate = len(temperatures) * [None] self._inverse_velocity = len(temperatures) * [None] + self._xs_shapes = None @property def name(self): @@ -161,8 +194,8 @@ class XSdata(object): return self._energy_groups @property - def delayed_groups(self): - return self._delayed_groups + def num_delayed_groups(self): + return self._num_delayed_groups @property def representation(self): @@ -184,10 +217,6 @@ class XSdata(object): def scatter_format(self): return self._scatter_format - @property - def scatter_shape(self): - return self._scatter_shape - @property def order(self): return self._order @@ -256,9 +285,39 @@ class XSdata(object): else: return self._order + @property + def xs_shapes(self): + + if self._xs_shapes is None: + + self._xs_shapes = {} + self._xs_shapes["[G]"] = (self.energy_groups.num_groups,) + self._xs_shapes["[G']"] = (self.energy_groups.num_groups,) + self._xs_shapes["[G][G']"] = (self.energy_groups.num_groups, + self.energy_groups.num_groups) + self._xs_shapes["[DG]"] = (self.num_delayed_groups,) + self._xs_shapes["[DG][G]"] = (self.num_delayed_groups, + self.energy_groups.num_groups) + self._xs_shapes["[DG][G']"] = (self.num_delayed_groups, + self.energy_groups.num_groups) + self._xs_shapes["[DG][G][G']"] = (self.num_delayed_groups, + self.energy_groups.num_groups, + self.energy_groups.num_groups) + self._xs_shapes["[Order][G][G']"] \ + = (self.num_orders, self.energy_groups.num_groups, + self.energy_groups.num_groups) + + # If representation is by angle prepend num polar and num azim + if self.representation == 'angle': + for key,shapes in self._xs_shapes.items(): + self._xs_shapes[key] \ + = (self.num_polar, self.num_azimuthal) + shapes + + return self._xs_shapes + @name.setter def name(self, name): - check_type('name for XSdata', name, basestring) + check_type('name for XSdata', name, string_types) self._name = name @energy_groups.setter @@ -274,14 +333,16 @@ class XSdata(object): self._energy_groups = energy_groups - @delayed_groups.setter - def delayed_groups(self, delayed_groups): + @num_delayed_groups.setter + def num_delayed_groups(self, num_delayed_groups): - # Check validity of delayed_groups - check_type('delayed_groups', delayed_groups, int) - check_greater_than('delayed_groups', delayed_groups, 0, equality=True) - - self._delayed_groups = delayed_groups + # Check validity of num_delayed_groups + check_type('num_delayed_groups', num_delayed_groups, int) + check_less_than('num_delayed_groups', num_delayed_groups, + openmc.mgxs.MAX_DELAYED_GROUPS, equality=True) + check_greater_than('num_delayed_groups', num_delayed_groups, 0, + equality=True) + self._num_delayed_groups = num_delayed_groups @representation.setter def representation(self, representation): @@ -292,6 +353,7 @@ class XSdata(object): @atomic_weight_ratio.setter def atomic_weight_ratio(self, atomic_weight_ratio): + # Check validity of type and that the atomic_weight_ratio value is > 0 check_type('atomic_weight_ratio', atomic_weight_ratio, Real) check_greater_than('atomic_weight_ratio', atomic_weight_ratio, 0.0) @@ -299,8 +361,8 @@ class XSdata(object): @temperatures.setter def temperatures(self, temperatures): - check_iterable_type('temperatures', temperatures, Real) + check_iterable_type('temperatures', temperatures, Real) self._temperatures = np.array(temperatures) @scatter_format.setter @@ -310,12 +372,6 @@ class XSdata(object): check_value('scatter_format', scatter_format, _SCATTER_TYPES) self._scatter_format = scatter_format - @scatter_shape.setter - def scatter_shape(self, scatter_shape): - # check to see it is of a valid type and value - check_value('scatter_shape', scatter_shape, _SCATTER_SHAPES) - self._scatter_shape = scatter_shape - @order.setter def order(self, order): @@ -393,11 +449,7 @@ class XSdata(object): check_type('total', total, Iterable, expected_iter_type=Real) # Get the accepted shapes for this xs - if self.representation is 'isotropic': - shapes = [(self.energy_groups.num_groups,)] - else: - shapes = [(self.num_polar, self.num_azimuthal, - self.energy_groups.num_groups)] + shapes = [self.xs_shapes["[G]"]] # Convert to a numpy array so we can easily get the shape for checking total = np.asarray(total) @@ -429,11 +481,7 @@ class XSdata(object): check_type('absorption', absorption, Iterable, expected_iter_type=Real) # Get the accepted shapes for this xs - if self.representation is 'isotropic': - shapes = [(self.energy_groups.num_groups,)] - else: - shapes = [(self.num_polar, self.num_azimuthal, - self.energy_groups.num_groups)] + shapes = [self.xs_shapes["[G]"]] # Convert to a numpy array so we can easily get the shape for checking absorption = np.asarray(absorption) @@ -465,11 +513,7 @@ class XSdata(object): check_type('fission', fission, Iterable, expected_iter_type=Real) # Get the accepted shapes for this xs - if self.representation is 'isotropic': - shapes = [(self.energy_groups.num_groups,)] - else: - shapes = [(self.num_polar, self.num_azimuthal, - self.energy_groups.num_groups)] + shapes = [self.xs_shapes["[G]"]] # Convert to a numpy array so we can easily get the shape for checking fission = np.asarray(fission) @@ -505,11 +549,7 @@ class XSdata(object): expected_iter_type=Real) # Get the accepted shapes for this xs - if self.representation is 'isotropic': - shapes = [(self.energy_groups.num_groups,)] - else: - shapes = [(self.num_polar, self.num_azimuthal, - self.energy_groups.num_groups)] + shapes = [self.xs_shapes["[G]"]] # Convert to a numpy array so we can easily get the shape for checking kappa_fission = np.asarray(kappa_fission) @@ -542,11 +582,7 @@ class XSdata(object): """ # Get the accepted shapes for this xs - if self.representation is 'isotropic': - shapes = [(self.energy_groups.num_groups,)] - else: - shapes = [(self.num_polar, self.num_azimuthal, - self.energy_groups.num_groups)] + shapes = [self.xs_shapes["[G']"]] # Convert to a numpy array so we can easily get the shape for checking chi = np.asarray(chi) @@ -576,11 +612,7 @@ class XSdata(object): """ # Get the accepted shapes for this xs - if self.representation is 'isotropic': - shapes = [(self.energy_groups.num_groups,)] - else: - shapes = [(self.num_polar, self.num_azimuthal, - self.energy_groups.num_groups)] + shapes = [self.xs_shapes["[G']"]] # Convert to a numpy array so we can easily get the shape for checking chi_prompt = np.asarray(chi_prompt) @@ -610,14 +642,7 @@ class XSdata(object): """ # Get the accepted shapes for this xs - if self.representation is 'isotropic': - shapes = [(self.energy_groups.num_groups,), - (self.delayed_groups, self.energy_groups.num_groups)] - else: - shapes = [(self.num_polar, self.num_azimuthal, - self.energy_groups.num_groups), - (self.delayed_groups, self.num_polar, self.num_azimuthal, - self.energy_groups.num_groups)] + shapes = [self.xs_shapes["[G']"], self.xs_shapes["[DG][G']"]] # Convert to a numpy array so we can easily get the shape for checking chi_delayed = np.asarray(chi_delayed) @@ -647,13 +672,7 @@ class XSdata(object): """ # Get the accepted shapes for this xs - if self.representation is 'isotropic': - shapes = [(self.delayed_groups,), - (self.delayed_groups, self.energy_groups.num_groups)] - else: - shapes = [(self.delayed_groups, self.num_polar, self.num_azimuthal, - self.energy_groups.num_groups), - (self.delayed_groups, self.num_polar, self.num_azimuthal)] + shapes = [self.xs_shapes["[DG]"], self.xs_shapes["[DG][G]"]] # Convert to a numpy array so we can easily get the shape for checking beta = np.asarray(beta) @@ -685,13 +704,7 @@ class XSdata(object): check_type('decay_rate', decay_rate, Iterable, expected_iter_type=Real) # Get the accepted shapes for this xs - if self.representation is 'isotropic': - shapes = [(self.delayed_groups,), - (self.delayed_groups, self.energy_groups.num_groups)] - else: - shapes = [(self.delayed_groups, self.num_polar, self.num_azimuthal, - self.energy_groups.num_groups), - (self.delayed_groups, self.num_polar, self.num_azimuthal)] + shapes = [self.xs_shapes["[DG]"], self.xs_shapes["[DG][G]"]] # Convert to a numpy array so we can easily get the shape for checking decay_rate = np.asarray(decay_rate) @@ -721,13 +734,7 @@ class XSdata(object): """ # Get the accepted shapes for this xs - if self.representation is 'isotropic': - shapes = [(self.num_orders, self.energy_groups.num_groups, - self.energy_groups.num_groups)] - else: - shapes = [(self.num_polar, self.num_azimuthal, self.num_orders, - self.energy_groups.num_groups, - self.energy_groups.num_groups)] + shapes = [self.xs_shapes["[Order][G][G']"]] # Convert to a numpy array so we can easily get the shape for checking scatter = np.asarray(scatter) @@ -759,13 +766,7 @@ class XSdata(object): """ # Get the accepted shapes for this xs - if self.representation is 'isotropic': - shapes = [(self.energy_groups.num_groups, - self.energy_groups.num_groups)] - else: - shapes = [(self.num_polar, self.num_azimuthal, - self.energy_groups.num_groups, - self.energy_groups.num_groups)] + shapes = [self.xs_shapes["[G][G']"]] # Convert to a numpy array so we can easily get the shape for checking multiplicity = np.asarray(multiplicity) @@ -797,16 +798,7 @@ class XSdata(object): """ # Get the accepted shapes for this xs - if self.representation is 'isotropic': - shapes = [(self.energy_groups.num_groups,), - (self.energy_groups.num_groups, - self.energy_groups.num_groups)] - else: - shapes = [(self.num_polar, self.num_azimuthal, - self.energy_groups.num_groups), - (self.num_polar, self.num_azimuthal, - self.energy_groups.num_groups, - self.energy_groups.num_groups)] + shapes = [self.xs_shapes["[G]"], self.xs_shapes["[G][G']"]] # Convert to a numpy array so we can easily get the shape for checking nu_fission = np.asarray(nu_fission) @@ -839,17 +831,8 @@ class XSdata(object): """ - # Get the accepted shapes for this xs - if self.representation is 'isotropic': - shapes = [(self.energy_groups.num_groups,), - (self.energy_groups.num_groups, - self.energy_groups.num_groups)] - else: - shapes = [(self.num_polar, self.num_azimuthal, - self.energy_groups.num_groups), - (self.num_polar, self.num_azimuthal, - self.energy_groups.num_groups, - self.energy_groups.num_groups)] + # Get the accepted shapes for this xs + shapes = [self.xs_shapes["[G]"], self.xs_shapes["[G][G']"]] # Convert to a numpy array so we can easily get the shape for checking prompt_nu_fission = np.asarray(prompt_nu_fission) @@ -882,17 +865,8 @@ class XSdata(object): """ - # Get the accepted shapes for this xs - if self.representation is 'isotropic': - shapes = [(self.delayed_groups, self.energy_groups.num_groups,), - (self.delayed_groups, self.energy_groups.num_groups, - self.energy_groups.num_groups)] - else: - shapes = [(self.delayed_groups, self.num_polar, self.num_azimuthal, - self.energy_groups.num_groups), - (self.delayed_groups, self.num_polar, self.num_azimuthal, - self.energy_groups.num_groups, - self.energy_groups.num_groups)] + # Get the accepted shapes for this xs + shapes = [self.xs_shapes["[DG][G]"], self.xs_shapes["[DG][G][G']"]] # Convert to a numpy array so we can easily get the shape for checking delayed_nu_fission = np.asarray(delayed_nu_fission) @@ -926,11 +900,7 @@ class XSdata(object): expected_iter_type=Real) # Get the accepted shapes for this xs - if self.representation is 'isotropic': - shapes = [(self.energy_groups.num_groups,)] - else: - shapes = [(self.num_polar, self.num_azimuthal, - self.energy_groups.num_groups)] + shapes = [self.xs_shapes["[G]"]] # Convert to a numpy array so we can easily get the shape for checking inv_vel = np.asarray(inv_vel) @@ -975,8 +945,7 @@ class XSdata(object): check_type('total', total, (openmc.mgxs.TotalXS, openmc.mgxs.TransportXS)) check_value('energy_groups', total.energy_groups, [self.energy_groups]) - check_value('domain_type', total.domain_type, - ['universe', 'cell', 'material', 'mesh']) + check_value('domain_type', total.domain_type, openmc.mgxs.DOMAIN_TYPES) check_type('temperature', temperature, Real) check_value('temperature', temperature, self.temperatures) @@ -1022,7 +991,7 @@ class XSdata(object): check_value('energy_groups', absorption.energy_groups, [self.energy_groups]) check_value('domain_type', absorption.domain_type, - ['universe', 'cell', 'material', 'mesh']) + openmc.mgxs.DOMAIN_TYPES) check_type('temperature', temperature, Real) check_value('temperature', temperature, self.temperatures) @@ -1069,7 +1038,7 @@ class XSdata(object): check_value('energy_groups', fission.energy_groups, [self.energy_groups]) check_value('domain_type', fission.domain_type, - ['universe', 'cell', 'material', 'mesh']) + openmc.mgxs.DOMAIN_TYPES) check_type('temperature', temperature, Real) check_value('temperature', temperature, self.temperatures) @@ -1117,7 +1086,7 @@ class XSdata(object): check_value('energy_groups', nu_fission.energy_groups, [self.energy_groups]) check_value('domain_type', nu_fission.domain_type, - ['universe', 'cell', 'material', 'mesh']) + openmc.mgxs.DOMAIN_TYPES) check_type('temperature', temperature, Real) check_value('temperature', temperature, self.temperatures) @@ -1171,7 +1140,7 @@ class XSdata(object): check_value('energy_groups', prompt_nu_fission.energy_groups, [self.energy_groups]) check_value('domain_type', prompt_nu_fission.domain_type, - ['universe', 'cell', 'material', 'mesh']) + openmc.mgxs.DOMAIN_TYPES) check_type('temperature', temperature, Real) check_value('temperature', temperature, self.temperatures) @@ -1225,10 +1194,10 @@ class XSdata(object): openmc.mgxs.DelayedNuFissionMatrixXS)) check_value('energy_groups', delayed_nu_fission.energy_groups, [self.energy_groups]) - check_value('delayed_groups', delayed_nu_fission.num_delayed_groups, - [self.delayed_groups]) + check_value('num_delayed_groups', delayed_nu_fission.num_delayed_groups, + [self.num_delayed_groups]) check_value('domain_type', delayed_nu_fission.domain_type, - ['universe', 'cell', 'material', 'mesh']) + openmc.mgxs.DOMAIN_TYPES) check_type('temperature', temperature, Real) check_value('temperature', temperature, self.temperatures) @@ -1281,7 +1250,7 @@ class XSdata(object): check_value('energy_groups', k_fission.energy_groups, [self.energy_groups]) check_value('domain_type', k_fission.domain_type, - ['universe', 'cell', 'material', 'mesh']) + openmc.mgxs.DOMAIN_TYPES) check_type('temperature', temperature, Real) check_value('temperature', temperature, self.temperatures) @@ -1325,8 +1294,7 @@ class XSdata(object): check_type('chi', chi, openmc.mgxs.Chi) check_value('energy_groups', chi.energy_groups, [self.energy_groups]) - check_value('domain_type', chi.domain_type, - ['universe', 'cell', 'material', 'mesh']) + check_value('domain_type', chi.domain_type, openmc.mgxs.DOMAIN_TYPES) check_type('temperature', temperature, Real) check_value('temperature', temperature, self.temperatures) @@ -1371,7 +1339,7 @@ class XSdata(object): check_value('energy_groups', chi_prompt.energy_groups, [self.energy_groups]) check_value('domain_type', chi_prompt.domain_type, - ['universe', 'cell', 'material', 'mesh']) + openmc.mgxs.DOMAIN_TYPES) check_type('temperature', temperature, Real) check_value('temperature', temperature, self.temperatures) @@ -1416,10 +1384,10 @@ class XSdata(object): check_type('chi_delayed', chi_delayed, openmc.mgxs.ChiDelayed) check_value('energy_groups', chi_delayed.energy_groups, [self.energy_groups]) - check_value('delayed_groups', chi_delayed.num_delayed_groups, - [self.delayed_groups]) + check_value('num_delayed_groups', chi_delayed.num_delayed_groups, + [self.num_delayed_groups]) check_value('domain_type', chi_delayed.domain_type, - ['universe', 'cell', 'material', 'mesh']) + openmc.mgxs.DOMAIN_TYPES) check_type('temperature', temperature, Real) check_value('temperature', temperature, self.temperatures) @@ -1462,10 +1430,9 @@ class XSdata(object): """ check_type('beta', beta, openmc.mgxs.Beta) - check_value('delayed_groups', beta.num_delayed_groups, - [self.delayed_groups]) - check_value('domain_type', beta.domain_type, - ['universe', 'cell', 'material', 'mesh']) + check_value('num_delayed_groups', beta.num_delayed_groups, + [self.num_delayed_groups]) + check_value('domain_type', beta.domain_type, openmc.mgxs.DOMAIN_TYPES) check_type('temperature', temperature, Real) check_value('temperature', temperature, self.temperatures) @@ -1508,10 +1475,10 @@ class XSdata(object): """ check_type('decay_rate', decay_rate, openmc.mgxs.DecayRate) - check_value('delayed_groups', decay_rate.num_delayed_groups, - [self.delayed_groups]) + check_value('num_delayed_groups', decay_rate.num_delayed_groups, + [self.num_delayed_groups]) check_value('domain_type', decay_rate.domain_type, - ['universe', 'cell', 'material', 'mesh']) + openmc.mgxs.DOMAIN_TYPES) check_type('temperature', temperature, Real) check_value('temperature', temperature, self.temperatures) @@ -1561,7 +1528,7 @@ class XSdata(object): check_value('energy_groups', scatter.energy_groups, [self.energy_groups]) check_value('domain_type', scatter.domain_type, - ['universe', 'cell', 'material', 'mesh']) + openmc.mgxs.DOMAIN_TYPES) check_type('temperature', temperature, Real) check_value('temperature', temperature, self.temperatures) @@ -1643,7 +1610,7 @@ class XSdata(object): check_value('energy_groups', nuscatter.energy_groups, [self.energy_groups]) check_value('domain_type', nuscatter.domain_type, - ['universe', 'cell', 'material', 'mesh']) + openmc.mgxs.DOMAIN_TYPES) check_type('temperature', temperature, Real) check_value('temperature', temperature, self.temperatures) @@ -1657,8 +1624,7 @@ class XSdata(object): check_value('energy_groups', scatter.energy_groups, [self.energy_groups]) check_value('domain_type', scatter.domain_type, - ['universe', 'cell', 'material', 'mesh']) - + openmc.mgxs.DOMAIN_TYPES) i = np.where(self.temperatures == temperature)[0][0] if self.representation == 'isotropic': nuscatt = nuscatter.get_xs(nuclides=nuclide, @@ -1701,10 +1667,9 @@ class XSdata(object): if self.num_polar is not None: grp.attrs['num-polar'] = self.num_polar + grp.attrs['scatter_shape'] = np.string_("[Order][G][G']") if self.scatter_format is not None: grp.attrs['scatter_format'] = np.string_(self.scatter_format) - if self.scatter_shape is not None: - grp.attrs['scatter_shape'] = np.string_(self.scatter_shape) if self.order is not None: grp.attrs['order'] = self.order @@ -1890,22 +1855,22 @@ class MGXSLibrary(object): ---------- energy_groups : openmc.mgxs.EnergyGroups Energy group structure - delayed_groups : int + num_delayed_groups : int Num delayed groups Attributes ---------- energy_groups : openmc.mgxs.EnergyGroups Energy group structure. - delayed_groups : int + num_delayed_groups : int Num delayed groups xsdatas : Iterable of openmc.XSdata Iterable of multi-Group cross section data objects """ - def __init__(self, energy_groups, delayed_groups=0): + def __init__(self, energy_groups, num_delayed_groups=0): self.energy_groups = energy_groups - self.delayed_groups = delayed_groups + self.num_delayed_groups = num_delayed_groups self._xsdatas = [] @property @@ -1913,8 +1878,8 @@ class MGXSLibrary(object): return self._energy_groups @property - def delayed_groups(self): - return self._delayed_groups + def num_delayed_groups(self): + return self._num_delayed_groups @property def temperatures(self): @@ -1929,10 +1894,14 @@ class MGXSLibrary(object): check_type('energy groups', energy_groups, openmc.mgxs.EnergyGroups) self._energy_groups = energy_groups - @delayed_groups.setter - def delayed_groups(self, delayed_groups): - check_type('delayed groups', delayed_groups, int) - self._delayed_groups = delayed_groups + @num_delayed_groups.setter + def num_delayed_groups(self, num_delayed_groups): + check_type('num_delayed_groups', num_delayed_groups, int) + check_greater_than('num_delayed_groups', num_delayed_groups, 0, + equality=True) + check_less_than('num_delayed_groups', num_delayed_groups, + openmc.mgxs.MAX_DELAYED_GROUPS, equality=True) + self._num_delayed_groups = num_delayed_groups def add_xsdata(self, xsdata): """Add an XSdata entry to the file. @@ -1997,12 +1966,12 @@ class MGXSLibrary(object): """ - check_type('filename', filename, basestring) + check_type('filename', filename, string_types) # Create and write to the HDF5 file file = h5py.File(filename, "w") file.attrs['energy_groups'] = self.energy_groups.num_groups - file.attrs['delayed_groups'] = self.delayed_groups + file.attrs['delayed_groups'] = self.num_delayed_groups file.attrs['group structure'] = self.energy_groups.group_edges for xsdata in self._xsdatas: diff --git a/openmc/model/triso.py b/openmc/model/triso.py index 5525ea559..046bd4515 100644 --- a/openmc/model/triso.py +++ b/openmc/model/triso.py @@ -10,6 +10,7 @@ from heapq import heappush, heappop from math import pi, sin, cos, floor, log10, sqrt from abc import ABCMeta, abstractproperty, abstractmethod +from six import add_metaclass import numpy as np try: import scipy.spatial @@ -95,6 +96,7 @@ class TRISO(openmc.Cell): k_min:k_max+1, j_min:j_max+1, i_min:i_max+1])) +@add_metaclass(ABCMeta) class _Domain(object): """Container in which to pack particles. @@ -123,9 +125,6 @@ class _Domain(object): Volume of the container. """ - - __metaclass__ = ABCMeta - def __init__(self, particle_radius, center=[0., 0., 0.]): self._cell_length = None self._limits = None diff --git a/openmc/nuclide.py b/openmc/nuclide.py index 11c59e687..5b844582c 100644 --- a/openmc/nuclide.py +++ b/openmc/nuclide.py @@ -2,10 +2,9 @@ from numbers import Integral import sys import warnings -from openmc.checkvalue import check_type +from six import string_types -if sys.version_info[0] >= 3: - basestring = str +from openmc.checkvalue import check_type class Nuclide(object): @@ -39,7 +38,7 @@ class Nuclide(object): return False else: return True - elif isinstance(other, basestring) and other == self.name: + elif isinstance(other, string_types) and other == self.name: return True else: return False @@ -73,7 +72,7 @@ class Nuclide(object): @name.setter def name(self, name): - check_type('name', name, basestring) + check_type('name', name, string_types) self._name = name if '-' in name: diff --git a/openmc/plots.py b/openmc/plots.py index 6915604a3..48af6f23c 100644 --- a/openmc/plots.py +++ b/openmc/plots.py @@ -4,14 +4,13 @@ from xml.etree import ElementTree as ET import sys import warnings +from six import string_types import numpy as np import openmc import openmc.checkvalue as cv from openmc.clean_xml import clean_xml_indentation -if sys.version_info[0] >= 3: - basestring = str # A static variable for auto-generated Plot IDs AUTO_PLOT_ID = 10000 @@ -166,7 +165,7 @@ class Plot(object): @name.setter def name(self, name): - cv.check_type('plot name', name, basestring) + cv.check_type('plot name', name, string_types) self._name = name @width.setter @@ -191,24 +190,24 @@ class Plot(object): @filename.setter def filename(self, filename): - cv.check_type('filename', filename, basestring) + cv.check_type('filename', filename, string_types) self._filename = filename @color.setter def color(self, color): - cv.check_type('plot color', color, basestring) + cv.check_type('plot color', color, string_types) cv.check_value('plot color', color, ['cell', 'mat']) self._color = color @type.setter def type(self, plottype): - cv.check_type('plot type', plottype, basestring) + cv.check_type('plot type', plottype, string_types) cv.check_value('plot type', plottype, ['slice', 'voxel']) self._type = plottype @basis.setter def basis(self, basis): - cv.check_type('plot basis', basis, basestring) + cv.check_type('plot basis', basis, string_types) cv.check_value('plot basis', basis, ['xy', 'xz', 'yz']) self._basis = basis @@ -387,7 +386,7 @@ class Plot(object): cv.check_less_than('alpha', alpha, 1., equality=True) # Get a background (R,G,B) tuple to apply in alpha compositing - if isinstance(background, basestring): + if isinstance(background, string_types): if background == 'white': background = (255, 255, 255) elif background == 'black': diff --git a/openmc/region.py b/openmc/region.py index a1b9e9fd0..ce970f812 100644 --- a/openmc/region.py +++ b/openmc/region.py @@ -1,11 +1,13 @@ from abc import ABCMeta, abstractmethod from collections import Iterable +from six import add_metaclass import numpy as np from openmc.checkvalue import check_type +@add_metaclass(ABCMeta) class Region(object): """Region of space that can be assigned to a cell. @@ -16,9 +18,6 @@ class Region(object): created through operators of the Surface and Region classes. """ - - __metaclass__ = ABCMeta - def __and__(self, other): return Intersection(self, other) diff --git a/openmc/settings.py b/openmc/settings.py index d24af185f..a214b02f3 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -4,15 +4,13 @@ import warnings from xml.etree import ElementTree as ET import sys +from six import string_types import numpy as np from openmc.clean_xml import clean_xml_indentation import openmc.checkvalue as cv from openmc import Nuclide, VolumeCalculation, Source -if sys.version_info[0] >= 3: - basestring = str - class Settings(object): """Settings used for an OpenMC simulation. @@ -549,7 +547,7 @@ class Settings(object): @output_path.setter def output_path(self, output_path): - cv.check_type('output path', output_path, basestring) + cv.check_type('output path', output_path, string_types) self._output_path = output_path @verbosity.setter @@ -605,12 +603,12 @@ class Settings(object): @cross_sections.setter def cross_sections(self, cross_sections): - cv.check_type('cross sections', cross_sections, basestring) + cv.check_type('cross sections', cross_sections, string_types) self._cross_sections = cross_sections @multipole_library.setter def multipole_library(self, multipole_library): - cv.check_type('cross sections', multipole_library, basestring) + cv.check_type('cross sections', multipole_library, string_types) self._multipole_library = multipole_library @ptables.setter diff --git a/openmc/source.py b/openmc/source.py index ee32cd0f4..1aee43514 100644 --- a/openmc/source.py +++ b/openmc/source.py @@ -2,13 +2,12 @@ from numbers import Real import sys from xml.etree import ElementTree as ET +from six import string_types + from openmc.stats.univariate import Univariate from openmc.stats.multivariate import UnitSphere, Spatial import openmc.checkvalue as cv -if sys.version_info[0] >= 3: - basestring = str - class Source(object): """Distribution of phase space coordinates for source sites. @@ -79,7 +78,7 @@ class Source(object): @file.setter def file(self, filename): - cv.check_type('source file', filename, basestring) + cv.check_type('source file', filename, string_types) self._file = filename @space.setter diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 1a97b695b..aaa5c0b84 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -9,9 +9,6 @@ import numpy as np import openmc import openmc.checkvalue as cv -if sys.version > '3': - long = int - class StatePoint(object): """State information on a simulation at a certain point in time (at the end diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index e49a94ee1..ca25cf5fb 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -5,15 +5,14 @@ from numbers import Real import sys from xml.etree import ElementTree as ET +from six import add_metaclass import numpy as np import openmc.checkvalue as cv from openmc.stats.univariate import Univariate, Uniform -if sys.version_info[0] >= 3: - basestring = str - +@add_metaclass(ABCMeta) class UnitSphere(object): """Distribution of points on the unit sphere. @@ -31,9 +30,6 @@ class UnitSphere(object): Direction from which polar angle is measured """ - - __metaclass__ = ABCMeta - def __init__(self, reference_uvw=None): self._reference_uvw = None if reference_uvw is not None: @@ -184,6 +180,7 @@ class Monodirectional(UnitSphere): return element +@add_metaclass(ABCMeta) class Spatial(object): """Distribution of locations in three-dimensional Euclidean space. @@ -191,9 +188,6 @@ class Spatial(object): distributions of source sites. """ - - __metaclass__ = ABCMeta - def __init__(self): pass diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index ce0f0fae1..dcbb9982c 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -4,18 +4,18 @@ from numbers import Real import sys from xml.etree import ElementTree as ET +from six import add_metaclass import numpy as np import openmc.checkvalue as cv from openmc.mixin import EqualityMixin -if sys.version_info[0] >= 3: - basestring = str _INTERPOLATION_SCHEMES = ['histogram', 'linear-linear', 'linear-log', 'log-linear', 'log-log'] +@add_metaclass(ABCMeta) class Univariate(EqualityMixin): """Probability distribution of a single random variable. @@ -23,9 +23,6 @@ class Univariate(EqualityMixin): specific probability distribution. """ - - __metaclass__ = ABCMeta - def __init__(self): pass diff --git a/openmc/surface.py b/openmc/surface.py index c33c4ee74..c88c4ccc7 100644 --- a/openmc/surface.py +++ b/openmc/surface.py @@ -4,13 +4,12 @@ from xml.etree import ElementTree as ET import sys from math import sqrt +from six import add_metaclass, string_types import numpy as np from openmc.checkvalue import check_type, check_value, check_greater_than from openmc.region import Region, Intersection -if sys.version_info[0] >= 3: - basestring = str # A static variable for auto-generated Surface IDs AUTO_SURFACE_ID = 10000 @@ -134,14 +133,14 @@ class Surface(object): @name.setter def name(self, name): if name is not None: - check_type('surface name', name, basestring) + check_type('surface name', name, string_types) self._name = name else: self._name = '' @boundary_type.setter def boundary_type(self, boundary_type): - check_type('boundary type', boundary_type, basestring) + check_type('boundary type', boundary_type, string_types) check_value('boundary type', boundary_type, _BC_TYPES) self._boundary_type = boundary_type @@ -642,6 +641,7 @@ class ZPlane(Plane): return point[2] - self.z0 +@add_metaclass(ABCMeta) class Cylinder(Surface): """A cylinder whose length is parallel to the x-, y-, or z-axis. @@ -677,9 +677,6 @@ class Cylinder(Surface): Type of the surface """ - - __metaclass__ = ABCMeta - def __init__(self, surface_id=None, boundary_type='transmission', R=1., name=''): super(Cylinder, self).__init__(surface_id, boundary_type, name=name) @@ -1210,7 +1207,7 @@ class Sphere(Surface): z = point[2] - self.z0 return x**2 + y**2 + z**2 - self.r**2 - +@add_metaclass(ABCMeta) class Cone(Surface): """A conical surface parallel to the x-, y-, or z-axis. @@ -1257,9 +1254,6 @@ class Cone(Surface): Type of the surface """ - - __metaclass__ = ABCMeta - def __init__(self, surface_id=None, boundary_type='transmission', x0=0., y0=0., z0=0., R2=1., name=''): super(Cone, self).__init__(surface_id, boundary_type, name=name) diff --git a/openmc/tallies.py b/openmc/tallies.py index f9daa7a22..604713145 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -11,15 +11,13 @@ import sys import warnings from xml.etree import ElementTree as ET +from six import string_types import numpy as np import openmc import openmc.checkvalue as cv from openmc.clean_xml import clean_xml_indentation -if sys.version_info[0] >= 3: - basestring = str - # "Static" variable for auto-generated Tally IDs AUTO_TALLY_ID = 10000 @@ -33,9 +31,9 @@ _PRODUCT_TYPES = ['tensor', 'entrywise'] # The following indicate acceptable types when setting Tally.scores, # Tally.nuclides, and Tally.filters -_SCORE_CLASSES = (basestring, openmc.CrossScore, openmc.AggregateScore) -_NUCLIDE_CLASSES = (basestring, openmc.Nuclide, openmc.CrossNuclide, - openmc.AggregateNuclide) +_SCORE_CLASSES = string_types + (openmc.CrossScore, openmc.AggregateScore) +_NUCLIDE_CLASSES = string_types + (openmc.Nuclide, openmc.CrossNuclide, + openmc.AggregateNuclide) _FILTER_CLASSES = (openmc.Filter, openmc.CrossFilter, openmc.AggregateFilter) # Valid types of estimators @@ -431,7 +429,7 @@ class Tally(object): @name.setter def name(self, name): if name is not None: - cv.check_type('tally name', name, basestring) + cv.check_type('tally name', name, string_types) self._name = name else: self._name = '' @@ -478,7 +476,7 @@ class Tally(object): raise ValueError(msg) # If score is a string, strip whitespace - if isinstance(score, basestring): + if isinstance(score, string_types): scores[i] = score.strip() self._scores = cv.CheckedList(_SCORE_CLASSES, 'tally scores', scores) @@ -1355,7 +1353,7 @@ class Tally(object): """ - cv.check_iterable_type('nuclides', nuclides, basestring) + cv.check_iterable_type('nuclides', nuclides, string_types) # Determine the score indices from any of the requested scores if nuclides: @@ -1390,7 +1388,7 @@ class Tally(object): """ for score in scores: - if not isinstance(score, (basestring, openmc.CrossScore)): + if not isinstance(score, string_types + (openmc.CrossScore,)): msg = 'Unable to get score indices for score "{0}" in Tally ' \ 'ID="{1}" since it is not a string or CrossScore'\ .format(score, self.id) @@ -1585,7 +1583,7 @@ class Tally(object): column_name = 'score' for score in self.scores: - if isinstance(score, (basestring, openmc.CrossScore)): + if isinstance(score, string_types + (openmc.CrossScore,)): scores.append(str(score)) elif isinstance(score, openmc.AggregateScore): scores.append(score.name) @@ -1700,13 +1698,13 @@ class Tally(object): msg = 'The Tally ID="{0}" has no data to export'.format(self.id) raise KeyError(msg) - if not isinstance(filename, basestring): + if not isinstance(filename, string_types): msg = 'Unable to export the results for Tally ID="{0}" to ' \ 'filename="{1}" since it is not a ' \ 'string'.format(self.id, filename) raise ValueError(msg) - elif not isinstance(directory, basestring): + elif not isinstance(directory, string_types): msg = 'Unable to export the results for Tally ID="{0}" to ' \ 'directory="{1}" since it is not a ' \ 'string'.format(self.id, directory) @@ -2354,11 +2352,11 @@ class Tally(object): raise ValueError(msg) # Check that the scores are valid - if not isinstance(score1, (basestring, openmc.CrossScore)): + if not isinstance(score1, string_types + (openmc.CrossScore,)): msg = 'Unable to swap score1 "{0}" in Tally ID="{1}" since it is ' \ 'not a string or CrossScore'.format(score1, self.id) raise ValueError(msg) - elif not isinstance(score2, (basestring, openmc.CrossScore)): + elif not isinstance(score2, string_types + (openmc.CrossScore,)): msg = 'Unable to swap score2 "{0}" in Tally ID="{1}" since it is ' \ 'not a string or CrossScore'.format(score2, self.id) raise ValueError(msg) diff --git a/openmc/trigger.py b/openmc/trigger.py index f23838dcf..69ec8c620 100644 --- a/openmc/trigger.py +++ b/openmc/trigger.py @@ -4,10 +4,9 @@ import sys import warnings from collections import Iterable -import openmc.checkvalue as cv +from six import string_types -if sys.version_info[0] >= 3: - basestring = str +import openmc.checkvalue as cv class Trigger(object): @@ -77,7 +76,7 @@ class Trigger(object): @scores.setter def scores(self, scores): - cv.check_type('trigger scores', scores, Iterable, basestring) + cv.check_type('trigger scores', scores, Iterable, string_types) # Set scores making sure not to have duplicates self._scores = [] diff --git a/openmc/universe.py b/openmc/universe.py index c8fb89a38..545b05d5a 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -3,13 +3,12 @@ from numbers import Integral import random import sys +from six import string_types import numpy as np import openmc import openmc.checkvalue as cv -if sys.version_info[0] >= 3: - basestring = str # A dictionary for storing IDs of cell elements that have already been written, # used to optimize the writing process @@ -118,7 +117,7 @@ class Universe(object): @name.setter def name(self, name): if name is not None: - cv.check_type('universe name', name, basestring) + cv.check_type('universe name', name, string_types) self._name = name else: self._name = '' diff --git a/scripts/openmc-ace-to-hdf5 b/scripts/openmc-ace-to-hdf5 index dd115d175..bfc1c1a54 100755 --- a/scripts/openmc-ace-to-hdf5 +++ b/scripts/openmc-ace-to-hdf5 @@ -108,7 +108,7 @@ elif args.xsdata is not None: for line in xsdata: words = line.split() if len(words) >= 9: - path = os.path.join(os.path.dirname(args.xsdata, words[8])) + path = os.path.join(os.path.dirname(args.xsdata), words[8]) if path not in ace_libraries: ace_libraries.append(path) diff --git a/data/convert_mcnp_70.py b/scripts/openmc-convert-mcnp70-data similarity index 85% rename from data/convert_mcnp_70.py rename to scripts/openmc-convert-mcnp70-data index e68bd848e..a3081e3ee 100755 --- a/data/convert_mcnp_70.py +++ b/scripts/openmc-convert-mcnp70-data @@ -1,7 +1,7 @@ #!/usr/bin/env python from __future__ import print_function -from argparse import ArgumentParser +import argparse from collections import defaultdict import glob import os @@ -9,8 +9,21 @@ import os import openmc.data -# Get path to MCNP data -parser = ArgumentParser() +description = """ +Convert ENDF/B-VII.0 ACE data from the MCNP5/6 distribution into an HDF5 library +that can be used by OpenMC. This assumes that you have a directory containing +files named endf70a, endf70b, ..., endf70k, and endf70sab. + +""" + +class CustomFormatter(argparse.ArgumentDefaultsHelpFormatter, + argparse.RawDescriptionHelpFormatter): + pass + +parser = argparse.ArgumentParser( + description=description, + formatter_class=CustomFormatter +) parser.add_argument('-d', '--destination', default='mcnp_endfb70', help='Directory to create new library in') parser.add_argument('mcnpdata', help='Directory containing endf70[a-k] and endf70sab') diff --git a/data/convert_mcnp_71.py b/scripts/openmc-convert-mcnp71-data similarity index 84% rename from data/convert_mcnp_71.py rename to scripts/openmc-convert-mcnp71-data index 7e7fd923f..944095919 100755 --- a/data/convert_mcnp_71.py +++ b/scripts/openmc-convert-mcnp71-data @@ -1,7 +1,7 @@ #!/usr/bin/env python from __future__ import print_function -from argparse import ArgumentParser +import argparse from collections import defaultdict import glob import os @@ -9,8 +9,21 @@ import os import openmc.data -# Get path to MCNP data -parser = ArgumentParser() +description = """ +Convert ENDF/B-VII.1 ACE data from the MCNP6 distribution into an HDF5 library +that can be used by OpenMC. This assumes that you have a directory containing +subdirectories 'endf71x' and 'ENDF71SaB'. + +""" + +class CustomFormatter(argparse.ArgumentDefaultsHelpFormatter, + argparse.RawDescriptionHelpFormatter): + pass + +parser = argparse.ArgumentParser( + description=description, + formatter_class=CustomFormatter +) parser.add_argument('-d', '--destination', default='mcnp_endfb71', help='Directory to create new library in') parser.add_argument('-f', '--fission_energy_release', diff --git a/data/get_jeff_data.py b/scripts/openmc-get-jeff-data similarity index 92% rename from data/get_jeff_data.py rename to scripts/openmc-get-jeff-data index d0e5839b9..3166b3854 100755 --- a/data/get_jeff_data.py +++ b/scripts/openmc-get-jeff-data @@ -10,18 +10,17 @@ import glob import argparse from string import digits +from six.moves import input +from six.moves.urllib.request import urlopen + import openmc.data -try: - from urllib.request import urlopen -except ImportError: - from urllib2 import urlopen -if sys.version_info[0] < 3: - askuser = raw_input -else: - askuser = input +description = """ +Download JEFF 3.2 ACE data from OECD/NEA and convert it to a multi-temperature +HDF5 library for use with OpenMC. +""" download_warning = """ WARNING: This script will download approximately 9 GB of data. Extracting and @@ -32,14 +31,21 @@ space. Note that if you don't need all 11 temperatures, you can modify the Are you sure you want to continue? ([y]/n) """ -parser = argparse.ArgumentParser() +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') parser.add_argument('-d', '--destination', default='jeff-3.2-hdf5', help='Directory to create new library in') args = parser.parse_args() -response = askuser(download_warning) if not args.batch else 'y' +response = input(download_warning) if not args.batch else 'y' if response.lower().startswith('n'): sys.exit() @@ -82,7 +88,7 @@ for f in files: files_complete.append(f) continue else: - overwrite = askuser('Overwrite {}? ([y]/n) '.format(f)) + overwrite = input('Overwrite {}? ([y]/n) '.format(f)) if overwrite.lower().startswith('n'): continue diff --git a/data/get_multipole_data.py b/scripts/openmc-get-multipole-data similarity index 85% rename from data/get_multipole_data.py rename to scripts/openmc-get-multipole-data index d51c196dc..bf0add284 100755 --- a/data/get_multipole_data.py +++ b/scripts/openmc-get-multipole-data @@ -10,18 +10,27 @@ import glob import hashlib import argparse -parser = argparse.ArgumentParser() +from six.moves import input +from six.moves.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() -try: - from urllib.request import urlopen -except ImportError: - from urllib2 import urlopen - -cwd = os.getcwd() -sys.path.insert(0, os.path.join(cwd, '..')) baseUrl = 'https://github.com/smharper/windowed_multipole_library/blob/master/' files = ['multipole_lib.tar.gz?raw=true'] @@ -54,10 +63,7 @@ for f in files: filesComplete.append(fname) continue else: - if sys.version_info[0] < 3: - overwrite = raw_input('Overwrite {0}? ([y]/n) '.format(fname)) - else: - overwrite = input('Overwrite {0}? ([y]/n) '.format(fname)) + overwrite = input('Overwrite {0}? ([y]/n) '.format(fname)) if overwrite.lower().startswith('n'): continue @@ -110,10 +116,7 @@ os.rmdir('wmp/multipole_lib') # Ask user to delete if not args.batch: - if sys.version_info[0] < 3: - response = raw_input('Delete *.tar.gz files? ([y]/n) ') - else: - response = input('Delete *.tar.gz files? ([y]/n) ') + response = input('Delete *.tar.gz files? ([y]/n) ') else: response = 'y' diff --git a/data/get_nndc_data.py b/scripts/openmc-get-nndc-data similarity index 70% rename from data/get_nndc_data.py rename to scripts/openmc-get-nndc-data index 5bec3865e..fe9d3ff5b 100755 --- a/data/get_nndc_data.py +++ b/scripts/openmc-get-nndc-data @@ -10,15 +10,31 @@ import glob import hashlib import argparse -parser = argparse.ArgumentParser() +from six.moves import input +from six.moves.urllib.request import urlopen + +import openmc.data + + +description = """ +Download ENDF/B-VII.1 ACE data from NNDC and convert it to an HDF5 library for +use with OpenMC. + +""" + + +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() -try: - from urllib.request import urlopen -except ImportError: - from urllib2 import urlopen baseUrl = 'http://www.nndc.bnl.gov/endf/b7.1/aceFiles/' files = ['ENDF-B-VII.1-neutron-293.6K.tar.gz', @@ -50,10 +66,7 @@ for f in files: filesComplete.append(f) continue else: - if sys.version_info[0] < 3: - overwrite = raw_input('Overwrite {0}? ([y]/n) '.format(f)) - else: - overwrite = input('Overwrite {0}? ([y]/n) '.format(f)) + overwrite = input('Overwrite {0}? ([y]/n) '.format(f)) if overwrite.lower().startswith('n'): continue @@ -65,7 +78,8 @@ for f in files: if not chunk: break fh.write(chunk) downloaded += len(chunk) - status = '{0:10} [{1:3.2f}%]'.format(downloaded, downloaded * 100. / file_size) + status = '{0:10} [{1:3.2f}%]'.format( + downloaded, downloaded * 100. / file_size) print(status + chr(8)*len(status), end='') print('') filesComplete.append(f) @@ -99,7 +113,7 @@ for f in files: for filename in glob.glob('nndc/293.6K/ENDF-B-VII.1-neutron-293.6K/*'): shutil.move(filename, 'nndc/293.6K/') -#=============================================================================== +# ============================================================================== # EDIT GRAPHITE ZAID (6012 to 6000) print('Changing graphite ZAID from 6012 to 6000') @@ -115,10 +129,7 @@ with open(graphite, 'w') as fh: # Ask user to delete if not args.batch: - if sys.version_info[0] < 3: - response = raw_input('Delete *.tar.gz files? ([y]/n) ') - else: - response = input('Delete *.tar.gz files? ([y]/n) ') + response = input('Delete *.tar.gz files? ([y]/n) ') else: response = 'y' @@ -130,27 +141,16 @@ if not response or response.lower().startswith('y'): os.remove(f) # ============================================================================== -# PROMPT USER TO GENERATE HDF5 LIBRARY +# GENERATE HDF5 LIBRARY -# Ask user to convert -if not args.batch: - if sys.version_info[0] < 3: - response = raw_input('Generate HDF5 library? ([y]/n) ') - else: - response = input('Generate HDF5 library? ([y]/n) ') -else: - response = 'y' +# get a list of all ACE files +ace_files = sorted(glob.glob(os.path.join('nndc', '**', '*.ace*'))) -# Convert files if requested -if not response or response.lower().startswith('y'): - # get a list of all ACE files - ace_files = sorted(glob.glob(os.path.join('nndc', '**', '*.ace*'))) +# Get path to fission energy release data +data_dir = os.path.dirname(sys.modules['openmc.data'].__file__) +fer_file = os.path.join(data_dir, 'fission_Q_data_endfb71.h5') - # Ensure 'import openmc.data' works in the openmc-ace-to-xml script - cwd = os.getcwd() - env = os.environ.copy() - env['PYTHONPATH'] = os.path.join(cwd, '..') - - subprocess.call(['../scripts/openmc-ace-to-hdf5', '-d', 'nndc_hdf5', - '--fission_energy_release', 'fission_Q_data_endfb71.h5'] - + ace_files, env=env) +pwd = os.path.dirname(os.path.realpath(__file__)) +ace2hdf5 = os.path.join(pwd, 'openmc-ace-to-hdf5') +subprocess.call([ace2hdf5, '-d', 'nndc_hdf5', '--fission_energy_release', + fer_file] + ace_files) diff --git a/scripts/openmc-plot-mesh-tally b/scripts/openmc-plot-mesh-tally index 04f1f06c6..cf17fabe9 100755 --- a/scripts/openmc-plot-mesh-tally +++ b/scripts/openmc-plot-mesh-tally @@ -5,6 +5,11 @@ import os import sys +import six.moves.tkinter as tk +import six.moves.tkinter_filedialog as filedialog +import six.moves.tkinter_font as font +import six.moves.tkinter_messagebox as messagebox +import six.moves.tkinter_ttk as ttk from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from matplotlib.backends.backend_tkagg import NavigationToolbar2TkAgg from matplotlib.figure import Figure @@ -13,19 +18,6 @@ import numpy as np from openmc.statepoint import StatePoint -if sys.version_info[0] < 3: - import Tkinter as tk - import tkFileDialog as filedialog - import tkFont as font - import tkMessageBox as messagebox - import ttk as ttk -else: - import tkinter as tk - import tkinter.filedialog as filedialog - import tkinter.font as font - import tkinter.messagebox as messagebox - import tkinter.ttk as ttk - class MeshPlotter(tk.Frame): def __init__(self, parent, filename): diff --git a/scripts/openmc-update-mgxs b/scripts/openmc-update-mgxs index 658be9fef..cad48d0e3 100755 --- a/scripts/openmc-update-mgxs +++ b/scripts/openmc-update-mgxs @@ -85,13 +85,13 @@ if __name__ == '__main__': temp = np.array(temp.split()) group_structure = temp.astype(np.float) energy_groups = openmc.mgxs.EnergyGroups(group_structure) - temp = tree.find('inverse_velocities') + temp = tree.find('inverse-velocity') if temp is not None: temp = temp.text.strip() temp = np.array(temp.split()) - inverse_velocities = temp.astype(np.float) + inverse_velocity = temp.astype(np.float) else: - inverse_velocities = None + inverse_velocity = None xsd = [] names = [] @@ -166,8 +166,8 @@ if __name__ == '__main__': total.shape = xsd[i].vector_shape xsd[i].set_total(total, temperature) - if inverse_velocities is not None: - xsd[i].set_inverse_velocities(inverse_velocities, temperature) + if inverse_velocity is not None: + xsd[i].set_inverse_velocity(inverse_velocity, temperature) temp = get_data(xsdata_elem, 'absorption') temp = np.array(temp.split()) diff --git a/setup.py b/setup.py index da98506d3..0885c28a8 100755 --- a/setup.py +++ b/setup.py @@ -39,7 +39,7 @@ kwargs = {'name': 'openmc', if have_setuptools: kwargs.update({ # Required dependencies - 'install_requires': ['numpy>=1.9', 'h5py', 'matplotlib'], + 'install_requires': ['six', 'numpy>=1.9', 'h5py', 'matplotlib'], # Optional dependencies 'extras_require': { @@ -51,7 +51,7 @@ if have_setuptools: # Data files 'package_data': { - 'openmc.data': ['mass.mas12'] + 'openmc.data': ['mass.mas12', 'fission_Q_data_endfb71.h5'] }, }) diff --git a/src/input_xml.F90 b/src/input_xml.F90 index f6d8e9b9a..324fce0c7 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -4665,8 +4665,6 @@ contains call read_attribute(num_delayed_groups, file_id, "delayed_groups") else num_delayed_groups = 0 - call write_message("WARNING: delayed_groups element not provided so & - &number of delayed groups set to 0") end if allocate(rev_energy_bins(num_energy_groups + 1)) diff --git a/src/tally.F90 b/src/tally.F90 index 0cdd259a4..cc21c67c1 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -1250,10 +1250,10 @@ contains if (i_nuclide > 0) then score = score * nucxs % get_xs('inverse-velocity', p_g, UVW=p_uvw) & - / nucxs % get_xs('total', p_g, UVW=p_uvw) * flux + / matxs % get_xs('absorption', p_g, UVW=p_uvw) * flux else score = score * matxs % get_xs('inverse-velocity', p_g, UVW=p_uvw) & - / matxs % get_xs('total', p_g, UVW=p_uvw) * flux + / matxs % get_xs('absorption', p_g, UVW=p_uvw) * flux end if else @@ -1587,7 +1587,7 @@ contains if (i_nuclide > 0) then score = score * nucxs % get_xs('delayed-nu-fission', & p_g, UVW=p_uvw, dg=d) / & - nucxs % get_xs('absorption', p_g, UVW=p_uvw) + matxs % get_xs('absorption', p_g, UVW=p_uvw) else score = score * matxs % get_xs('delayed-nu-fission', & p_g, UVW=p_uvw, dg=d) / & @@ -1602,7 +1602,7 @@ contains score = p % absorb_wgt * flux if (i_nuclide > 0) then score = score * nucxs % get_xs('delayed-nu-fission', p_g, & - UVW=p_uvw) / nucxs % get_xs('absorption', p_g, UVW=p_uvw) + UVW=p_uvw) / matxs % get_xs('absorption', p_g, UVW=p_uvw) else score = score * matxs % get_xs('delayed-nu-fission', p_g, & UVW=p_uvw) / matxs % get_xs('absorption', p_g, UVW=p_uvw) @@ -1724,7 +1724,7 @@ contains score = score * nucxs % get_xs('decay rate', p_g, & UVW=p_uvw, dg=d) * & nucxs % get_xs('delayed-nu-fission', p_g, & - UVW=p_uvw, dg=d) / nucxs % get_xs('absorption', & + UVW=p_uvw, dg=d) / matxs % get_xs('absorption', & p_g, UVW=p_uvw) else score = score * matxs % get_xs('decay rate', p_g, & @@ -1751,7 +1751,7 @@ contains score = score + p % absorb_wgt * & nucxs % get_xs('decay rate', p_g, UVW=p_uvw, dg=d) * & nucxs % get_xs('delayed-nu-fission', p_g, UVW=p_uvw, & - dg=d) / nucxs % get_xs('absorption', p_g, UVW=p_uvw) + dg=d) / matxs % get_xs('absorption', p_g, UVW=p_uvw) else score = score + p % absorb_wgt * & matxs % get_xs('decay rate', p_g, UVW=p_uvw, dg=d) * & diff --git a/tests/test_mgxs_library_condense/test_mgxs_library_condense.py b/tests/test_mgxs_library_condense/test_mgxs_library_condense.py index d3f2bc08e..19c6ffda9 100644 --- a/tests/test_mgxs_library_condense/test_mgxs_library_condense.py +++ b/tests/test_mgxs_library_condense/test_mgxs_library_condense.py @@ -23,9 +23,6 @@ class MGXSTestHarness(PyAPITestHarness): energy_groups = openmc.mgxs.EnergyGroups(group_edges=[0, 0.625e-6, 20.]) - # Initialize a six-delayed-group structure - delayed_groups = list(range(1,7)) - # Initialize MGXS Library for a few cross section types self.mgxs_lib = openmc.mgxs.Library(self._input_set.geometry) self.mgxs_lib.by_nuclide = False @@ -34,7 +31,7 @@ class MGXSTestHarness(PyAPITestHarness): self.mgxs_lib.mgxs_types = openmc.mgxs.MGXS_TYPES + \ openmc.mgxs.MDGXS_TYPES self.mgxs_lib.energy_groups = energy_groups - self.mgxs_lib.delayed_groups = delayed_groups + self.mgxs_lib.num_delayed_groups = 6 self.mgxs_lib.legendre_order = 3 self.mgxs_lib.domain_type = 'material' self.mgxs_lib.build_library() diff --git a/tests/test_mgxs_library_distribcell/test_mgxs_library_distribcell.py b/tests/test_mgxs_library_distribcell/test_mgxs_library_distribcell.py index 940985d91..5c402749a 100644 --- a/tests/test_mgxs_library_distribcell/test_mgxs_library_distribcell.py +++ b/tests/test_mgxs_library_distribcell/test_mgxs_library_distribcell.py @@ -22,9 +22,6 @@ class MGXSTestHarness(PyAPITestHarness): # Initialize a one-group structure energy_groups = openmc.mgxs.EnergyGroups(group_edges=[0, 20.]) - # Initialize a six-delayed-group structure - delayed_groups = list(range(1,7)) - # Initialize MGXS Library for a few cross section types # for one material-filled cell in the geometry self.mgxs_lib = openmc.mgxs.Library(self._input_set.geometry) @@ -34,7 +31,7 @@ class MGXSTestHarness(PyAPITestHarness): self.mgxs_lib.mgxs_types = openmc.mgxs.MGXS_TYPES + \ openmc.mgxs.MDGXS_TYPES self.mgxs_lib.energy_groups = energy_groups - self.mgxs_lib.delayed_groups = delayed_groups + self.mgxs_lib.num_delayed_groups = 6 self.mgxs_lib.legendre_order = 3 self.mgxs_lib.domain_type = 'distribcell' cells = self.mgxs_lib.openmc_geometry.get_all_material_cells() diff --git a/tests/test_mgxs_library_hdf5/test_mgxs_library_hdf5.py b/tests/test_mgxs_library_hdf5/test_mgxs_library_hdf5.py index b4d7e5dbb..959f9e70a 100644 --- a/tests/test_mgxs_library_hdf5/test_mgxs_library_hdf5.py +++ b/tests/test_mgxs_library_hdf5/test_mgxs_library_hdf5.py @@ -24,9 +24,6 @@ class MGXSTestHarness(PyAPITestHarness): energy_groups = openmc.mgxs.EnergyGroups(group_edges=[0, 0.625e-6, 20.]) - # Initialize a six-delayed-group structure - delayed_groups = list(range(1,7)) - # Initialize MGXS Library for a few cross section types self.mgxs_lib = openmc.mgxs.Library(self._input_set.geometry) self.mgxs_lib.by_nuclide = False @@ -35,7 +32,7 @@ class MGXSTestHarness(PyAPITestHarness): self.mgxs_lib.mgxs_types = openmc.mgxs.MGXS_TYPES + \ openmc.mgxs.MDGXS_TYPES self.mgxs_lib.energy_groups = energy_groups - self.mgxs_lib.delayed_groups = delayed_groups + self.mgxs_lib.num_delayed_groups = 6 self.mgxs_lib.legendre_order = 3 self.mgxs_lib.domain_type = 'material' self.mgxs_lib.build_library() diff --git a/tests/test_mgxs_library_mesh/test_mgxs_library_mesh.py b/tests/test_mgxs_library_mesh/test_mgxs_library_mesh.py index 1f31bd566..3a42ccd34 100644 --- a/tests/test_mgxs_library_mesh/test_mgxs_library_mesh.py +++ b/tests/test_mgxs_library_mesh/test_mgxs_library_mesh.py @@ -18,9 +18,6 @@ class MGXSTestHarness(PyAPITestHarness): # Initialize a one-group structure energy_groups = openmc.mgxs.EnergyGroups(group_edges=[0, 20.]) - # Initialize a six-delayed-group structure - delayed_groups = list(range(1,7)) - # Initialize MGXS Library for a few cross section types # for one material-filled cell in the geometry self.mgxs_lib = openmc.mgxs.Library(self._input_set.geometry) @@ -30,7 +27,7 @@ class MGXSTestHarness(PyAPITestHarness): self.mgxs_lib.mgxs_types = openmc.mgxs.MGXS_TYPES + \ openmc.mgxs.MDGXS_TYPES self.mgxs_lib.energy_groups = energy_groups - self.mgxs_lib.delayed_groups = delayed_groups + self.mgxs_lib.num_delayed_groups = 6 self.mgxs_lib.legendre_order = 3 self.mgxs_lib.domain_type = 'mesh' diff --git a/tests/test_mgxs_library_no_nuclides/test_mgxs_library_no_nuclides.py b/tests/test_mgxs_library_no_nuclides/test_mgxs_library_no_nuclides.py index edd41f1c5..a8eea412b 100644 --- a/tests/test_mgxs_library_no_nuclides/test_mgxs_library_no_nuclides.py +++ b/tests/test_mgxs_library_no_nuclides/test_mgxs_library_no_nuclides.py @@ -23,9 +23,6 @@ class MGXSTestHarness(PyAPITestHarness): energy_groups = openmc.mgxs.EnergyGroups(group_edges=[0, 0.625e-6, 20.]) - # Initialize a six-delayed-group structure - delayed_groups = list(range(1,7)) - # Initialize MGXS Library for a few cross section types self.mgxs_lib = openmc.mgxs.Library(self._input_set.geometry) self.mgxs_lib.by_nuclide = False @@ -34,7 +31,7 @@ class MGXSTestHarness(PyAPITestHarness): self.mgxs_lib.mgxs_types = openmc.mgxs.MGXS_TYPES + \ openmc.mgxs.MDGXS_TYPES self.mgxs_lib.energy_groups = energy_groups - self.mgxs_lib.delayed_groups = delayed_groups + self.mgxs_lib.num_delayed_groups = 6 self.mgxs_lib.legendre_order = 3 self.mgxs_lib.domain_type = 'material' self.mgxs_lib.build_library()