mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-27 21:55:41 -04:00
Merge pull request #920 from paulromano/c-api-round2
Changes and improvements to C API Python bindings
This commit is contained in:
commit
d84bd669f2
19 changed files with 399 additions and 256 deletions
|
|
@ -33,7 +33,9 @@ Classes
|
|||
:nosignatures:
|
||||
:template: myclass.rst
|
||||
|
||||
openmc.capi.CellView
|
||||
openmc.capi.MaterialView
|
||||
openmc.capi.NuclideView
|
||||
openmc.capi.TallyView
|
||||
openmc.capi.Cell
|
||||
openmc.capi.EnergyFilter
|
||||
openmc.capi.MaterialFilter
|
||||
openmc.capi.Material
|
||||
openmc.capi.Nuclide
|
||||
openmc.capi.Tally
|
||||
|
|
|
|||
|
|
@ -108,9 +108,9 @@ class CrossNuclide(object):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
left_nuclide : Nuclide or CrossNuclide
|
||||
left_nuclide : openmc.Nuclide or CrossNuclide
|
||||
The left nuclide in the outer product
|
||||
right_nuclide : Nuclide or CrossNuclide
|
||||
right_nuclide : openmc.Nuclide or CrossNuclide
|
||||
The right nuclide in the outer product
|
||||
binary_op : str
|
||||
The tally arithmetic binary operator (e.g., '+', '-', etc.) used to
|
||||
|
|
@ -118,9 +118,9 @@ class CrossNuclide(object):
|
|||
|
||||
Attributes
|
||||
----------
|
||||
left_nuclide : Nuclide or CrossNuclide
|
||||
left_nuclide : openmc.Nuclide or CrossNuclide
|
||||
The left nuclide in the outer product
|
||||
right_nuclide : Nuclide or CrossNuclide
|
||||
right_nuclide : openmc.Nuclide or CrossNuclide
|
||||
The right nuclide in the outer product
|
||||
binary_op : str
|
||||
The tally arithmetic binary operator (e.g., '+', '-', etc.) used to
|
||||
|
|
@ -510,7 +510,7 @@ class AggregateNuclide(object):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
nuclides : Iterable of str or Nuclide or CrossNuclide
|
||||
nuclides : Iterable of str or openmc.Nuclide or CrossNuclide
|
||||
The nuclides included in the aggregation
|
||||
aggregate_op : str
|
||||
The tally aggregation operator (e.g., 'sum', 'avg', etc.) used
|
||||
|
|
@ -518,7 +518,7 @@ class AggregateNuclide(object):
|
|||
|
||||
Attributes
|
||||
----------
|
||||
nuclides : Iterable of str or Nuclide or CrossNuclide
|
||||
nuclides : Iterable of str or openmc.Nuclide or CrossNuclide
|
||||
The nuclides included in the aggregation
|
||||
aggregate_op : str
|
||||
The tally aggregation operator (e.g., 'sum', 'avg', etc.) used
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ objects in the :mod:`openmc.capi` subpackage, for example:
|
|||
"""
|
||||
|
||||
from ctypes import CDLL
|
||||
import os
|
||||
import sys
|
||||
from warnings import warn
|
||||
|
||||
|
|
@ -25,10 +26,21 @@ if sys.platform == 'darwin':
|
|||
else:
|
||||
_suffix = 'so'
|
||||
|
||||
# Open shared library
|
||||
_filename = pkg_resources.resource_filename(
|
||||
__name__, 'libopenmc.{}'.format(_suffix))
|
||||
_dll = CDLL(_filename)
|
||||
if os.environ.get('READTHEDOCS', None) != 'True':
|
||||
# Open shared library
|
||||
_filename = pkg_resources.resource_filename(
|
||||
__name__, 'libopenmc.{}'.format(_suffix))
|
||||
_dll = CDLL(_filename)
|
||||
else:
|
||||
# For documentation builds, we don't actually have the shared library
|
||||
# available. Instead, we create a mock object so that when the modules
|
||||
# within the openmc.capi package try to configure arguments and return
|
||||
# values for symbols, no errors occur
|
||||
try:
|
||||
from unittest.mock import Mock
|
||||
except ImportError:
|
||||
from mock import Mock
|
||||
_dll = Mock()
|
||||
|
||||
from .error import *
|
||||
from .core import *
|
||||
|
|
@ -38,3 +50,6 @@ from .cell import *
|
|||
from .filter import *
|
||||
from .tally import *
|
||||
from .settings import settings
|
||||
|
||||
warn("The Python bindings to OpenMC's C API are still unstable "
|
||||
"and may change substantially in future releases.", FutureWarning)
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@ import numpy as np
|
|||
from numpy.ctypeslib import as_array
|
||||
|
||||
from . import _dll
|
||||
from .core import _View
|
||||
from .core import _FortranObjectWithID
|
||||
from .error import _error_handler
|
||||
from .material import MaterialView
|
||||
from .material import Material
|
||||
|
||||
__all__ = ['CellView', 'cells']
|
||||
__all__ = ['Cell', 'cells']
|
||||
|
||||
# Cell functions
|
||||
_dll.openmc_cell_get_id.argtypes = [c_int32, POINTER(c_int32)]
|
||||
|
|
@ -31,11 +31,11 @@ _dll.openmc_get_cell_index.restype = c_int
|
|||
_dll.openmc_get_cell_index.errcheck = _error_handler
|
||||
|
||||
|
||||
class CellView(_View):
|
||||
"""View of a cell.
|
||||
class Cell(_FortranObjectWithID):
|
||||
"""Cell stored internally.
|
||||
|
||||
This class exposes a cell that is stored internally in the OpenMC solver. To
|
||||
obtain a view of a cell with a given ID, use the
|
||||
This class exposes a cell that is stored internally in the OpenMC
|
||||
library. To obtain a view of a cell with a given ID, use the
|
||||
:data:`openmc.capi.nuclides` mapping.
|
||||
|
||||
Parameters
|
||||
|
|
@ -53,7 +53,7 @@ class CellView(_View):
|
|||
|
||||
def __new__(cls, *args):
|
||||
if args not in cls.__instances:
|
||||
instance = super().__new__(cls)
|
||||
instance = super(Cell, self).__new__(cls)
|
||||
cls.__instances[args] = instance
|
||||
return cls.__instances[args]
|
||||
|
||||
|
|
@ -72,9 +72,9 @@ class CellView(_View):
|
|||
|
||||
if fill_type.value == 1:
|
||||
if n.value > 1:
|
||||
return [MaterialView(i) for i in indices[:n.value]]
|
||||
return [Material(index=i) for i in indices[:n.value]]
|
||||
else:
|
||||
return MaterialView(indices[0])
|
||||
return Material(index=indices[0])
|
||||
else:
|
||||
raise NotImplementedError
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ class CellView(_View):
|
|||
n = len(fill)
|
||||
indices = (c_int*n)(*(m._index for m in fill))
|
||||
_dll.openmc_cell_set_fill(self._index, 1, 1, indices)
|
||||
elif isinstance(fill, MaterialView):
|
||||
elif isinstance(fill, Material):
|
||||
materials = [fill]
|
||||
indices = (c_int*1)(fill._index)
|
||||
_dll.openmc_cell_set_fill(self._index, 1, 1, indices)
|
||||
|
|
@ -108,12 +108,16 @@ class CellView(_View):
|
|||
class _CellMapping(Mapping):
|
||||
def __getitem__(self, key):
|
||||
index = c_int32()
|
||||
_dll.openmc_get_cell_index(key, index)
|
||||
return CellView(index.value)
|
||||
try:
|
||||
_dll.openmc_get_cell_index(key, index)
|
||||
except (AllocationError, InvalidIDError) as e:
|
||||
# __contains__ expects a KeyError to work correctly
|
||||
raise KeyError(str(e))
|
||||
return Cell(index.value)
|
||||
|
||||
def __iter__(self):
|
||||
for i in range(len(self)):
|
||||
yield CellView(i + 1).id
|
||||
yield Cell(i + 1).id
|
||||
|
||||
def __len__(self):
|
||||
return c_int32.in_dll(_dll, 'n_cells').value
|
||||
|
|
|
|||
|
|
@ -172,9 +172,15 @@ class _DLLGlobal(object):
|
|||
self.ctype.in_dll(_dll, self.name).value = value
|
||||
|
||||
|
||||
class _View(object):
|
||||
def __init__(self, index):
|
||||
self._index = index
|
||||
|
||||
class _FortranObject(object):
|
||||
def __repr__(self):
|
||||
return "{}[{}]".format(type(self).__name__, self._index)
|
||||
|
||||
|
||||
class _FortranObjectWithID(_FortranObject):
|
||||
def __init__(self, uid=None, new=True, index=None):
|
||||
# Creating the object has already been handled by __new__. In the
|
||||
# initializer, all we do is make sure that the object returned has an ID
|
||||
# assigned. If the array index of the object is out of bounds, an
|
||||
# OutOfBoundsError will be raised here by virtue of referencing self.id
|
||||
self.id
|
||||
|
|
|
|||
|
|
@ -39,9 +39,6 @@ class InvalidTypeError(Error):
|
|||
"""Tried to perform an operation on the wrong type."""
|
||||
|
||||
|
||||
_errmsg = (c_char*256).in_dll(_dll, 'openmc_err_msg')
|
||||
|
||||
|
||||
def _error_handler(err, func, args):
|
||||
"""Raise exception according to error code."""
|
||||
|
||||
|
|
@ -50,7 +47,8 @@ def _error_handler(err, func, args):
|
|||
return c_int.in_dll(_dll, s).value
|
||||
|
||||
# Get error message set by OpenMC library
|
||||
msg = _errmsg.value.decode()
|
||||
errmsg = (c_char*256).in_dll(_dll, 'openmc_err_msg')
|
||||
msg = errmsg.value.decode()
|
||||
|
||||
# Raise exception type corresponding to error code
|
||||
if err == errcode('e_allocate'):
|
||||
|
|
|
|||
|
|
@ -7,17 +7,17 @@ import numpy as np
|
|||
from numpy.ctypeslib import as_array
|
||||
|
||||
from . import _dll
|
||||
from .core import _View
|
||||
from .error import _error_handler
|
||||
from .material import MaterialView
|
||||
from .core import _FortranObjectWithID
|
||||
from .error import _error_handler, AllocationError, InvalidIDError
|
||||
from .material import Material
|
||||
|
||||
|
||||
__all__ = ['FilterView', 'AzimuthalFilterView', 'CellFilterView',
|
||||
'CellbornFilterView', 'CellfromFilterView', 'DistribcellFilterView',
|
||||
'DelayedGroupFilterView', 'EnergyFilterView', 'EnergyoutFilterView',
|
||||
'EnergyFunctionFilterView', 'MaterialFilterView', 'MeshFilterView',
|
||||
'MuFilterView', 'PolarFilterView', 'SurfaceFilterView',
|
||||
'UniverseFilterView', 'filters']
|
||||
__all__ = ['Filter', 'AzimuthalFilter', 'CellFilter',
|
||||
'CellbornFilter', 'CellfromFilter', 'DistribcellFilter',
|
||||
'DelayedGroupFilter', 'EnergyFilter', 'EnergyoutFilter',
|
||||
'EnergyFunctionFilter', 'MaterialFilter', 'MeshFilter',
|
||||
'MuFilter', 'PolarFilter', 'SurfaceFilter',
|
||||
'UniverseFilter', 'filters']
|
||||
|
||||
# Tally functions
|
||||
_dll.openmc_energy_filter_get_bins.argtypes = [
|
||||
|
|
@ -57,14 +57,43 @@ _dll.openmc_mesh_filter_set_mesh.restype = c_int
|
|||
_dll.openmc_mesh_filter_set_mesh.errcheck = _error_handler
|
||||
|
||||
|
||||
class FilterView(_View):
|
||||
class Filter(_FortranObjectWithID):
|
||||
__instances = WeakValueDictionary()
|
||||
|
||||
def __new__(cls, *args):
|
||||
if args not in cls.__instances:
|
||||
instance = super().__new__(cls)
|
||||
cls.__instances[args] = instance
|
||||
return cls.__instances[args]
|
||||
def __new__(cls, obj=None, uid=None, new=True, index=None):
|
||||
mapping = filters
|
||||
if index is None:
|
||||
if new:
|
||||
# Determine ID to assign
|
||||
if uid is None:
|
||||
try:
|
||||
uid = max(mapping) + 1
|
||||
except ValueError:
|
||||
uid = 1
|
||||
else:
|
||||
if uid in mapping:
|
||||
raise AllocationError('A filter with ID={} has already '
|
||||
'been allocated.'.format(uid))
|
||||
|
||||
# Resize internal array
|
||||
index = c_int32()
|
||||
_dll.openmc_extend_filters(1, index, None)
|
||||
|
||||
# Set the filter type -- note that the filter_type attribute
|
||||
# only exists on subclasses!
|
||||
_dll.openmc_filter_set_type(index, cls.filter_type.encode())
|
||||
index = index.value
|
||||
else:
|
||||
index = mapping[uid]._index
|
||||
|
||||
if index not in cls.__instances:
|
||||
instance = super(Filter, cls).__new__(cls)
|
||||
instance._index = index
|
||||
if uid is not None:
|
||||
instance.id = uid
|
||||
cls.__instances[index] = instance
|
||||
|
||||
return cls.__instances[index]
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
|
|
@ -77,7 +106,14 @@ class FilterView(_View):
|
|||
_dll.openmc_filter_set_id(self._index, filter_id)
|
||||
|
||||
|
||||
class EnergyFilterView(FilterView):
|
||||
class EnergyFilter(Filter):
|
||||
filter_type = 'energy'
|
||||
|
||||
def __init__(self, bins=None, uid=None, new=True, index=None):
|
||||
super(EnergyFilter, self).__init__(uid, new, index)
|
||||
if bins is not None:
|
||||
self.bins = bins
|
||||
|
||||
@property
|
||||
def bins(self):
|
||||
energies = POINTER(c_double)()
|
||||
|
|
@ -95,45 +131,52 @@ class EnergyFilterView(FilterView):
|
|||
self._index, len(energies), energies_p)
|
||||
|
||||
|
||||
class EnergyoutFilterView(FilterView):
|
||||
pass
|
||||
class EnergyoutFilter(Filter):
|
||||
filter_type = 'energyout'
|
||||
|
||||
|
||||
class AzimuthalFilterView(FilterView):
|
||||
pass
|
||||
class AzimuthalFilter(Filter):
|
||||
filter_type = 'azimuthal'
|
||||
|
||||
|
||||
class CellFilterView(FilterView):
|
||||
pass
|
||||
class CellFilter(Filter):
|
||||
filter_type = 'cell'
|
||||
|
||||
|
||||
class CellbornFilterView(FilterView):
|
||||
pass
|
||||
class CellbornFilter(Filter):
|
||||
filter_type = 'cellborn'
|
||||
|
||||
|
||||
class CellfromFilterView(FilterView):
|
||||
pass
|
||||
class CellfromFilter(Filter):
|
||||
filter_type = 'cellfrom'
|
||||
|
||||
|
||||
class DelayedGroupFilterView(FilterView):
|
||||
pass
|
||||
class DelayedGroupFilter(Filter):
|
||||
filter_type = 'delayedgroup'
|
||||
|
||||
|
||||
class DistribcellFilterView(FilterView):
|
||||
pass
|
||||
class DistribcellFilter(Filter):
|
||||
filter_type = 'distribcell'
|
||||
|
||||
|
||||
class EnergyFunctionFilterView(FilterView):
|
||||
pass
|
||||
class EnergyFunctionFilter(Filter):
|
||||
filter_type = 'energyfunction'
|
||||
|
||||
|
||||
class MaterialFilterView(FilterView):
|
||||
class MaterialFilter(Filter):
|
||||
filter_type = 'material'
|
||||
|
||||
def __init__(self, bins=None, uid=None, new=True, index=None):
|
||||
super(MaterialFilter, self).__init__(uid, new, index)
|
||||
if bins is not None:
|
||||
self.bins = bins
|
||||
|
||||
@property
|
||||
def bins(self):
|
||||
materials = POINTER(c_int32)()
|
||||
n = c_int32()
|
||||
_dll.openmc_material_filter_get_bins(self._index, materials, n)
|
||||
return [MaterialView(materials[i]) for i in range(n.value)]
|
||||
return [Material(index=materials[i]) for i in range(n.value)]
|
||||
|
||||
@bins.setter
|
||||
def bins(self, materials):
|
||||
|
|
@ -143,58 +186,43 @@ class MaterialFilterView(FilterView):
|
|||
|
||||
_dll.openmc_material_filter_set_bins(self._index, n, bins)
|
||||
|
||||
@classmethod
|
||||
def new(cls, bins=None, filter_id=None):
|
||||
# Determine filter ID to assign
|
||||
if filter_id is None:
|
||||
filter_id = max(filters) + 1
|
||||
|
||||
index = c_int32()
|
||||
_dll.openmc_extend_filters(1, index, None)
|
||||
_dll.openmc_filter_set_type(index, b'material')
|
||||
f = cls(index.value)
|
||||
f.id = filter_id
|
||||
if bins is not None:
|
||||
f.bins = bins
|
||||
return f
|
||||
class MeshFilter(Filter):
|
||||
filter_type = 'mesh'
|
||||
|
||||
|
||||
class MeshFilterView(FilterView):
|
||||
pass
|
||||
class MuFilter(Filter):
|
||||
filter_type = 'mu'
|
||||
|
||||
|
||||
class MuFilterView(FilterView):
|
||||
pass
|
||||
class PolarFilter(Filter):
|
||||
filter_type = 'polar'
|
||||
|
||||
|
||||
class PolarFilterView(FilterView):
|
||||
pass
|
||||
class SurfaceFilter(Filter):
|
||||
filter_type = 'surface'
|
||||
|
||||
|
||||
class SurfaceFilterView(FilterView):
|
||||
pass
|
||||
class UniverseFilter(Filter):
|
||||
filter_type = 'universe'
|
||||
|
||||
|
||||
class UniverseFilterView(FilterView):
|
||||
pass
|
||||
|
||||
|
||||
_filter_type_map = {
|
||||
'azimuthal': AzimuthalFilterView,
|
||||
'cell': CellFilterView,
|
||||
'cellborn': CellbornFilterView,
|
||||
'cellfrom': CellfromFilterView,
|
||||
'delayedgroup': DelayedGroupFilterView,
|
||||
'distribcell': DistribcellFilterView,
|
||||
'energy': EnergyFilterView,
|
||||
'energyout': EnergyoutFilterView,
|
||||
'energyfunction': EnergyFunctionFilterView,
|
||||
'material': MaterialFilterView,
|
||||
'mesh': MeshFilterView,
|
||||
'mu': MuFilterView,
|
||||
'polar': PolarFilterView,
|
||||
'surface': SurfaceFilterView,
|
||||
'universe': UniverseFilterView,
|
||||
_FILTER_TYPE_MAP = {
|
||||
'azimuthal': AzimuthalFilter,
|
||||
'cell': CellFilter,
|
||||
'cellborn': CellbornFilter,
|
||||
'cellfrom': CellfromFilter,
|
||||
'delayedgroup': DelayedGroupFilter,
|
||||
'distribcell': DistribcellFilter,
|
||||
'energy': EnergyFilter,
|
||||
'energyout': EnergyoutFilter,
|
||||
'energyfunction': EnergyFunctionFilter,
|
||||
'material': MaterialFilter,
|
||||
'mesh': MeshFilter,
|
||||
'mu': MuFilter,
|
||||
'polar': PolarFilter,
|
||||
'surface': SurfaceFilter,
|
||||
'universe': UniverseFilter,
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -202,18 +230,22 @@ def _get_filter(index):
|
|||
filter_type = create_string_buffer(20)
|
||||
_dll.openmc_filter_get_type(index, filter_type)
|
||||
filter_type = filter_type.value.decode()
|
||||
return _filter_type_map[filter_type](index)
|
||||
return _FILTER_TYPE_MAP[filter_type](index=index)
|
||||
|
||||
|
||||
class _FilterMapping(Mapping):
|
||||
def __getitem__(self, key):
|
||||
index = c_int32()
|
||||
_dll.openmc_get_filter_index(key, index)
|
||||
try:
|
||||
_dll.openmc_get_filter_index(key, index)
|
||||
except (AllocationError, InvalidIDError) as e:
|
||||
# __contains__ expects a KeyError to work correctly
|
||||
raise KeyError(str(e))
|
||||
return _get_filter(index.value)
|
||||
|
||||
def __iter__(self):
|
||||
for i in range(len(self)):
|
||||
yield TallyView(i + 1).id
|
||||
yield _get_filter(i + 1).id
|
||||
|
||||
def __len__(self):
|
||||
return c_int32.in_dll(_dll, 'n_filters').value
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@ from weakref import WeakValueDictionary
|
|||
import numpy as np
|
||||
from numpy.ctypeslib import as_array
|
||||
|
||||
from . import _dll, NuclideView
|
||||
from .core import _View
|
||||
from .error import _error_handler
|
||||
from . import _dll, Nuclide
|
||||
from .core import _FortranObjectWithID
|
||||
from .error import _error_handler, AllocationError, InvalidIDError
|
||||
|
||||
|
||||
__all__ = ['MaterialView', 'materials']
|
||||
__all__ = ['Material', 'materials']
|
||||
|
||||
# Material functions
|
||||
_dll.openmc_extend_materials.argtypes = [c_int32, POINTER(c_int32), POINTER(c_int32)]
|
||||
|
|
@ -43,16 +43,21 @@ _dll.openmc_material_set_id.restype = c_int
|
|||
_dll.openmc_material_set_id.errcheck = _error_handler
|
||||
|
||||
|
||||
class MaterialView(_View):
|
||||
"""View of a material.
|
||||
class Material(_FortranObjectWithID):
|
||||
"""Material stored internally.
|
||||
|
||||
This class exposes a material that is stored internally in the OpenMC
|
||||
solver. To obtain a view of a material with a given ID, use the
|
||||
library. To obtain a view of a material with a given ID, use the
|
||||
:data:`openmc.capi.materials` mapping.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
index : int
|
||||
uid : int or None
|
||||
Unique ID of the tally
|
||||
new : bool
|
||||
When `index` is None, this argument controls whether a new object is
|
||||
created or a view to an existing object is returned.
|
||||
index : int or None
|
||||
Index in the `materials` array.
|
||||
|
||||
Attributes
|
||||
|
|
@ -67,6 +72,36 @@ class MaterialView(_View):
|
|||
"""
|
||||
__instances = WeakValueDictionary()
|
||||
|
||||
def __new__(cls, uid=None, new=True, index=None):
|
||||
mapping = materials
|
||||
if index is None:
|
||||
if new:
|
||||
# Determine ID to assign
|
||||
if uid is None:
|
||||
try:
|
||||
uid = max(mapping) + 1
|
||||
except ValueError:
|
||||
uid = 1
|
||||
else:
|
||||
if uid in mapping:
|
||||
raise AllocationError('A material with ID={} has already '
|
||||
'been allocated.'.format(uid))
|
||||
|
||||
index = c_int32()
|
||||
_dll.openmc_extend_materials(1, index, None)
|
||||
index = index.value
|
||||
else:
|
||||
index = mapping[uid]._index
|
||||
|
||||
if index not in cls.__instances:
|
||||
instance = super(Material, cls).__new__(cls)
|
||||
instance._index = index
|
||||
if uid is not None:
|
||||
instance.id = uid
|
||||
cls.__instances[index] = instance
|
||||
|
||||
return cls.__instances[index]
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
mat_id = c_int32()
|
||||
|
|
@ -106,7 +141,7 @@ class MaterialView(_View):
|
|||
_dll.openmc_material_get_densities(self._index, nuclides, densities, n)
|
||||
|
||||
# Convert to appropriate types and return
|
||||
nuclide_list = [NuclideView(nuclides[i]).name for i in range(n.value)]
|
||||
nuclide_list = [Nuclide(nuclides[i]).name for i in range(n.value)]
|
||||
density_array = as_array(densities, (n.value,))
|
||||
return nuclide_list, density_array
|
||||
|
||||
|
|
@ -123,18 +158,6 @@ class MaterialView(_View):
|
|||
"""
|
||||
_dll.openmc_material_add_nuclide(self._index, name.encode(), density)
|
||||
|
||||
@classmethod
|
||||
def new(cls, material_id=None):
|
||||
# Determine ID to assign
|
||||
if material_id is None:
|
||||
material_id = max(materials) + 1
|
||||
|
||||
index = c_int32()
|
||||
_dll.openmc_extend_materials(1, index, None)
|
||||
mat = cls(index.value)
|
||||
mat.id = material_id
|
||||
return mat
|
||||
|
||||
def set_density(self, density):
|
||||
"""Set density of a material.
|
||||
|
||||
|
|
@ -171,12 +194,16 @@ class MaterialView(_View):
|
|||
class _MaterialMapping(Mapping):
|
||||
def __getitem__(self, key):
|
||||
index = c_int32()
|
||||
_dll.openmc_get_material_index(key, index)
|
||||
return MaterialView(index.value)
|
||||
try:
|
||||
_dll.openmc_get_material_index(key, index)
|
||||
except (AllocationError, InvalidIDError) as e:
|
||||
# __contains__ expects a KeyError to work correctly
|
||||
raise KeyError(str(e))
|
||||
return Material(index=index.value)
|
||||
|
||||
def __iter__(self):
|
||||
for i in range(len(self)):
|
||||
yield MaterialView(i + 1).id
|
||||
yield Material(index=i + 1).id
|
||||
|
||||
def __len__(self):
|
||||
return c_int32.in_dll(_dll, 'n_materials').value
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@ import numpy as np
|
|||
from numpy.ctypeslib import as_array
|
||||
|
||||
from . import _dll
|
||||
from .core import _View
|
||||
from .error import _error_handler
|
||||
from .core import _FortranObject
|
||||
from .error import _error_handler, DataError, AllocationError
|
||||
|
||||
|
||||
__all__ = ['NuclideView', 'nuclides', 'load_nuclide']
|
||||
__all__ = ['Nuclide', 'nuclides', 'load_nuclide']
|
||||
|
||||
# Nuclide functions
|
||||
_dll.openmc_get_nuclide_index.argtypes = [c_char_p, POINTER(c_int)]
|
||||
|
|
@ -36,8 +36,8 @@ def load_nuclide(name):
|
|||
_dll.openmc_load_nuclide(name.encode())
|
||||
|
||||
|
||||
class NuclideView(_View):
|
||||
"""View of a nuclide.
|
||||
class Nuclide(_FortranObject):
|
||||
"""Nuclide stored internally.
|
||||
|
||||
This class exposes a nuclide that is stored internally in the OpenMC
|
||||
solver. To obtain a view of a nuclide with a given name, use the
|
||||
|
|
@ -58,10 +58,13 @@ class NuclideView(_View):
|
|||
|
||||
def __new__(cls, *args):
|
||||
if args not in cls.__instances:
|
||||
instance = super().__new__(cls)
|
||||
instance = super(Nuclide, cls).__new__(cls)
|
||||
cls.__instances[args] = instance
|
||||
return cls.__instances[args]
|
||||
|
||||
def __init__(self, index):
|
||||
self._index = index
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
name = c_char_p()
|
||||
|
|
@ -78,12 +81,16 @@ class _NuclideMapping(Mapping):
|
|||
"""Provide mapping from nuclide name to index in nuclides array."""
|
||||
def __getitem__(self, key):
|
||||
index = c_int()
|
||||
_dll.openmc_get_nuclide_index(key.encode(), index)
|
||||
return NuclideView(index.value)
|
||||
try:
|
||||
_dll.openmc_get_nuclide_index(key.encode(), index)
|
||||
except (DataError, AllocationError) as e:
|
||||
# __contains__ expects a KeyError to work correctly
|
||||
raise KeyError(str(e))
|
||||
return Nuclide(index.value)
|
||||
|
||||
def __iter__(self):
|
||||
for i in range(len(self)):
|
||||
yield NuclideView(i + 1).name
|
||||
yield Nuclide(i + 1).name
|
||||
|
||||
def __len__(self):
|
||||
return c_int.in_dll(_dll, 'n_nuclides').value
|
||||
|
|
|
|||
|
|
@ -10,6 +10,10 @@ _RUN_MODES = {1: 'fixed source',
|
|||
4: 'particle restart',
|
||||
5: 'volume'}
|
||||
|
||||
_dll.openmc_set_seed.argtypes = [c_int64]
|
||||
_dll.openmc_set_seed.restype = c_int
|
||||
_dll.openmc_set_seed.errcheck = _error_handler
|
||||
|
||||
|
||||
class _Settings(object):
|
||||
# Attributes that are accessed through a descriptor
|
||||
|
|
@ -37,5 +41,13 @@ class _Settings(object):
|
|||
else:
|
||||
raise ValueError('Invalid run mode: {}'.format(mode))
|
||||
|
||||
@property
|
||||
def seed(self):
|
||||
return c_int64.in_dll(_dll, 'seed').value
|
||||
|
||||
@seed.setter
|
||||
def seed(self, seed):
|
||||
_dll.openmc_set_seed(seed)
|
||||
|
||||
|
||||
settings = _Settings()
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ from weakref import WeakValueDictionary
|
|||
|
||||
from numpy.ctypeslib import as_array
|
||||
|
||||
from . import _dll, NuclideView
|
||||
from .core import _View
|
||||
from .error import _error_handler
|
||||
from . import _dll, Nuclide
|
||||
from .core import _FortranObjectWithID
|
||||
from .error import _error_handler, AllocationError, InvalidIDError
|
||||
from .filter import _get_filter
|
||||
|
||||
|
||||
__all__ = ['TallyView', 'tallies']
|
||||
__all__ = ['Tally', 'tallies']
|
||||
|
||||
# Tally functions
|
||||
_dll.openmc_get_tally_index.argtypes = [c_int32, POINTER(c_int32)]
|
||||
|
|
@ -51,24 +51,29 @@ _dll.openmc_tally_set_type.restype = c_int
|
|||
_dll.openmc_tally_set_type.errcheck = _error_handler
|
||||
|
||||
|
||||
class TallyView(_View):
|
||||
"""View of a tally.
|
||||
class Tally(_FortranObjectWithID):
|
||||
"""Tally stored internally.
|
||||
|
||||
This class exposes a tally that is stored internally in the OpenMC
|
||||
solver. To obtain a view of a tally with a given ID, use the
|
||||
library. To obtain a view of a tally with a given ID, use the
|
||||
:data:`openmc.capi.tallies` mapping.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
index : int
|
||||
Index in the `tallies` array.
|
||||
uid : int or None
|
||||
Unique ID of the tally
|
||||
new : bool
|
||||
When `index` is None, this argument controls whether a new object is
|
||||
created or a view of an existing object is returned.
|
||||
index : int or None
|
||||
Index in the `tallies` array.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
id : int
|
||||
ID of the tally
|
||||
filters : list
|
||||
List of views to tally filters
|
||||
List of tally filters
|
||||
nuclides : list of str
|
||||
List of nuclides to score results for
|
||||
results : numpy.ndarray
|
||||
|
|
@ -77,11 +82,36 @@ class TallyView(_View):
|
|||
"""
|
||||
__instances = WeakValueDictionary()
|
||||
|
||||
def __new__(cls, *args):
|
||||
if args not in cls.__instances:
|
||||
instance = super().__new__(cls)
|
||||
cls.__instances[args] = instance
|
||||
return cls.__instances[args]
|
||||
def __new__(cls, uid=None, new=True, index=None):
|
||||
mapping = tallies
|
||||
if index is None:
|
||||
if new:
|
||||
# Determine ID to assign
|
||||
if uid is None:
|
||||
try:
|
||||
uid = max(mapping) + 1
|
||||
except ValueError:
|
||||
uid = 1
|
||||
else:
|
||||
if uid in mapping:
|
||||
raise AllocationError('A tally with ID={} has already '
|
||||
'been allocated.'.format(uid))
|
||||
|
||||
index = c_int32()
|
||||
_dll.openmc_extend_tallies(1, index, None)
|
||||
_dll.openmc_tally_set_type(index, b'generic')
|
||||
index = index.value
|
||||
else:
|
||||
index = mapping[uid]._index
|
||||
|
||||
if index not in cls.__instances:
|
||||
instance = super(Tally, cls).__new__(cls)
|
||||
instance._index = index
|
||||
if uid is not None:
|
||||
instance.id = uid
|
||||
cls.__instances[index] = instance
|
||||
|
||||
return cls.__instances[index]
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
|
|
@ -105,7 +135,7 @@ class TallyView(_View):
|
|||
nucs = POINTER(c_int)()
|
||||
n = c_int()
|
||||
_dll.openmc_tally_get_nuclides(self._index, nucs, n)
|
||||
return [NuclideView(nucs[i]).name if nucs[i] > 0 else 'total'
|
||||
return [Nuclide(nucs[i]).name if nucs[i] > 0 else 'total'
|
||||
for i in range(n.value)]
|
||||
|
||||
@property
|
||||
|
|
@ -143,7 +173,10 @@ class TallyView(_View):
|
|||
def new(cls, tally_id=None):
|
||||
# Determine ID to assign
|
||||
if tally_id is None:
|
||||
tally_id = max(tallies) + 1
|
||||
try:
|
||||
tally_id = max(tallies) + 1
|
||||
except ValueError:
|
||||
tally_id = 1
|
||||
|
||||
index = c_int32()
|
||||
_dll.openmc_extend_tallies(1, index, None)
|
||||
|
|
@ -156,12 +189,16 @@ class TallyView(_View):
|
|||
class _TallyMapping(Mapping):
|
||||
def __getitem__(self, key):
|
||||
index = c_int32()
|
||||
_dll.openmc_get_tally_index(key, index)
|
||||
return TallyView(index.value)
|
||||
try:
|
||||
_dll.openmc_get_tally_index(key, index)
|
||||
except (AllocationError, InvalidIDError) as e:
|
||||
# __contains__ expects a KeyError to work correctly
|
||||
raise KeyError(str(e))
|
||||
return Tally(index=index.value)
|
||||
|
||||
def __iter__(self):
|
||||
for i in range(len(self)):
|
||||
yield TallyView(i + 1).id
|
||||
yield Tally(index=i + 1).id
|
||||
|
||||
def __len__(self):
|
||||
return c_int32.in_dll(_dll, 'n_tallies').value
|
||||
|
|
|
|||
|
|
@ -606,7 +606,7 @@ class Library(object):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
domain : Material or Cell or Universe or Integral
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh or Integral
|
||||
The material, cell, or universe object of interest (or its ID)
|
||||
mgxs_type : {'total', 'transport', 'nu-transport', 'absorption', 'capture', 'fission', 'nu-fission', 'kappa-fission', 'scatter', 'nu-scatter', 'scatter matrix', 'nu-scatter matrix', 'multiplicity matrix', 'nu-fission matrix', chi', 'chi-prompt', 'inverse-velocity', 'prompt-nu-fission', 'prompt-nu-fission matrix', 'delayed-nu-fission', 'delayed-nu-fission matrix', 'chi-delayed', 'beta'}
|
||||
The type of multi-group cross section object to return
|
||||
|
|
@ -668,7 +668,7 @@ class Library(object):
|
|||
|
||||
Returns
|
||||
-------
|
||||
Library
|
||||
openmc.mgxs.Library
|
||||
A new multi-group cross section library condensed to the group
|
||||
structure of interest
|
||||
|
||||
|
|
@ -880,7 +880,7 @@ class Library(object):
|
|||
|
||||
Returns
|
||||
-------
|
||||
Library
|
||||
openmc.mgxs.Library
|
||||
A Library object loaded from the pickle binary file
|
||||
|
||||
See also
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ class MDGXS(MGXS):
|
|||
Reaction type (e.g., 'chi-delayed', 'beta', etc.)
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
domain : Material or Cell or Universe or Mesh
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh
|
||||
Domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'}
|
||||
Domain type for spatial homogenization
|
||||
|
|
@ -948,7 +948,7 @@ class ChiDelayed(MDGXS):
|
|||
Reaction type (e.g., 'total', 'nu-fission', etc.)
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
domain : Material or Cell or Universe or Mesh
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh
|
||||
Domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'}
|
||||
Domain type for spatial homogenization
|
||||
|
|
@ -1462,7 +1462,7 @@ class DelayedNuFissionXS(MDGXS):
|
|||
Reaction type (e.g., 'total', 'nu-fission', etc.)
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
domain : Material or Cell or Universe or Mesh
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh
|
||||
Domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'}
|
||||
Domain type for spatial homogenization
|
||||
|
|
@ -1598,7 +1598,7 @@ class Beta(MDGXS):
|
|||
Reaction type (e.g., 'total', 'nu-fission', etc.)
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
domain : Material or Cell or Universe or Mesh
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh
|
||||
Domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'}
|
||||
Domain type for spatial homogenization
|
||||
|
|
@ -1782,7 +1782,7 @@ class DecayRate(MDGXS):
|
|||
Reaction type (e.g., 'total', 'nu-fission', etc.)
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
domain : Material or Cell or Universe or Mesh
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh
|
||||
Domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'}
|
||||
Domain type for spatial homogenization
|
||||
|
|
@ -1959,7 +1959,7 @@ class MatrixMDGXS(MDGXS):
|
|||
Reaction type (e.g., 'total', 'nu-fission', etc.)
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
domain : Material or Cell or Universe or Mesh
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh
|
||||
Domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'}
|
||||
Domain type for spatial homogenization
|
||||
|
|
@ -2551,7 +2551,7 @@ class DelayedNuFissionMatrixXS(MatrixMDGXS):
|
|||
Reaction type (e.g., 'total', 'nu-fission', etc.)
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
domain : Material or Cell or Universe or Mesh
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh
|
||||
Domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'}
|
||||
Domain type for spatial homogenization
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ class MGXS(object):
|
|||
Reaction type (e.g., 'total', 'nu-fission', etc.)
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
domain : Material or Cell or Universe or Mesh
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh
|
||||
Domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'}
|
||||
Domain type for spatial homogenization
|
||||
|
|
@ -2018,7 +2018,7 @@ class MatrixMGXS(MGXS):
|
|||
Reaction type (e.g., 'total', 'nu-fission', etc.)
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
domain : Material or Cell or Universe or Mesh
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh
|
||||
Domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'}
|
||||
Domain type for spatial homogenization
|
||||
|
|
@ -2512,7 +2512,7 @@ class TotalXS(MGXS):
|
|||
Reaction type (e.g., 'total', 'nu-fission', etc.)
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
domain : Material or Cell or Universe or Mesh
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh
|
||||
Domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'}
|
||||
Domain type for spatial homogenization
|
||||
|
|
@ -2649,7 +2649,7 @@ class TransportXS(MGXS):
|
|||
If True, the cross section data will include neutron multiplication
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
domain : Material or Cell or Universe or Mesh
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh
|
||||
Domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'}
|
||||
Domain type for spatial homogenization
|
||||
|
|
@ -2858,7 +2858,7 @@ class AbsorptionXS(MGXS):
|
|||
Reaction type (e.g., 'total', 'nu-fission', etc.)
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
domain : Material or Cell or Universe or Mesh
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh
|
||||
Domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'}
|
||||
Domain type for spatial homogenization
|
||||
|
|
@ -2986,7 +2986,7 @@ class CaptureXS(MGXS):
|
|||
Reaction type (e.g., 'total', 'nu-fission', etc.)
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
domain : Material or Cell or Universe or Mesh
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh
|
||||
Domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'}
|
||||
Domain type for spatial homogenization
|
||||
|
|
@ -3140,7 +3140,7 @@ class FissionXS(MGXS):
|
|||
If true, computes cross sections which only includes prompt neutrons
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
domain : Material or Cell or Universe or Mesh
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh
|
||||
Domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'}
|
||||
Domain type for spatial homogenization
|
||||
|
|
@ -3309,7 +3309,7 @@ class KappaFissionXS(MGXS):
|
|||
Reaction type (e.g., 'total', 'nu-fission', etc.)
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
domain : Material or Cell or Universe or Mesh
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh
|
||||
Domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'}
|
||||
Domain type for spatial homogenization
|
||||
|
|
@ -3441,7 +3441,7 @@ class ScatterXS(MGXS):
|
|||
If True, the cross section data will include neutron multiplication
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
domain : Material or Cell or Universe or Mesh
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh
|
||||
Domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'}
|
||||
Domain type for spatial homogenization
|
||||
|
|
@ -3658,7 +3658,7 @@ class ScatterMatrixXS(MatrixMGXS):
|
|||
If True, the cross section data will include neutron multiplication
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
domain : Material or Cell or Universe or Mesh
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh
|
||||
Domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'}
|
||||
Domain type for spatial homogenization
|
||||
|
|
@ -4020,7 +4020,7 @@ class ScatterMatrixXS(MatrixMGXS):
|
|||
# Override the nuclides for tally arithmetic
|
||||
correction.nuclides = scatter_p1.nuclides
|
||||
self._xs_tally -= correction
|
||||
|
||||
|
||||
self._compute_xs()
|
||||
|
||||
return self._xs_tally
|
||||
|
|
@ -4749,7 +4749,7 @@ class MultiplicityMatrixXS(MatrixMGXS):
|
|||
Reaction type (e.g., 'total', 'nu-fission', etc.)
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
domain : Material or Cell or Universe or Mesh
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh
|
||||
Domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'}
|
||||
Domain type for spatial homogenization
|
||||
|
|
@ -4915,7 +4915,7 @@ class ScatterProbabilityMatrix(MatrixMGXS):
|
|||
Reaction type (e.g., 'total', 'nu-fission', etc.)
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
domain : Material or Cell or Universe or Mesh
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh
|
||||
Domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'}
|
||||
Domain type for spatial homogenization
|
||||
|
|
@ -5088,7 +5088,7 @@ class NuFissionMatrixXS(MatrixMGXS):
|
|||
If true, computes cross sections which only includes prompt neutrons
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
domain : Material or Cell or Universe or Mesh
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh
|
||||
Domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'}
|
||||
Domain type for spatial homogenization
|
||||
|
|
@ -5245,7 +5245,7 @@ class Chi(MGXS):
|
|||
If true, computes cross sections which only includes prompt neutrons
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
domain : Material or Cell or Universe or Mesh
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh
|
||||
Domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'}
|
||||
Domain type for spatial homogenization
|
||||
|
|
@ -5823,7 +5823,7 @@ class InverseVelocity(MGXS):
|
|||
Reaction type (e.g., 'total', 'nu-fission', etc.)
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
domain : Material or Cell or Universe or Mesh
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.Mesh
|
||||
Domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'}
|
||||
Domain type for spatial homogenization
|
||||
|
|
|
|||
|
|
@ -502,7 +502,7 @@ class Tally(IDManagerMixin):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
nuclide : str, Nuclide, CrossNuclide or AggregateNuclide
|
||||
nuclide : str, openmc.Nuclide, CrossNuclide or AggregateNuclide
|
||||
Nuclide to add to the tally. The nuclide should be a Nuclide object
|
||||
when a user is adding nuclides to a Tally for input file generation.
|
||||
The nuclide is a str when a Tally is created from a StatePoint file
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ module openmc_api
|
|||
use initialize, only: openmc_init
|
||||
use particle_header, only: Particle
|
||||
use plot, only: openmc_plot_geometry
|
||||
use random_lcg, only: seed, initialize_prng
|
||||
use random_lcg, only: seed, openmc_set_seed
|
||||
use settings
|
||||
use simulation_header
|
||||
use tally_header
|
||||
|
|
@ -212,6 +212,8 @@ contains
|
|||
!===============================================================================
|
||||
|
||||
subroutine openmc_hard_reset() bind(C)
|
||||
integer :: err
|
||||
|
||||
! Reset all tallies and timers
|
||||
call openmc_reset()
|
||||
|
||||
|
|
@ -220,8 +222,7 @@ contains
|
|||
total_gen = 0
|
||||
|
||||
! Reset the random number generator state
|
||||
seed = 1_8
|
||||
call initialize_prng()
|
||||
err = openmc_set_seed(1_8)
|
||||
end subroutine openmc_hard_reset
|
||||
|
||||
!===============================================================================
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ module initialize
|
|||
use message_passing
|
||||
use mgxs_data, only: read_mgxs, create_macro_xs
|
||||
use output, only: print_version, write_message, print_usage
|
||||
use random_lcg, only: initialize_prng
|
||||
use random_lcg, only: openmc_set_seed, seed
|
||||
use settings
|
||||
#ifdef _OPENMP
|
||||
use simulation_header, only: n_threads
|
||||
|
|
@ -44,6 +44,8 @@ contains
|
|||
subroutine openmc_init(intracomm) bind(C)
|
||||
integer, intent(in), optional :: intracomm ! MPI intracommunicator
|
||||
|
||||
integer :: err
|
||||
|
||||
! Copy the communicator to a new variable. This is done to avoid changing
|
||||
! the signature of this subroutine. If MPI is being used but no communicator
|
||||
! was passed, assume MPI_COMM_WORLD.
|
||||
|
|
@ -82,7 +84,7 @@ contains
|
|||
|
||||
! Initialize random number generator -- if the user specifies a seed, it
|
||||
! will be re-initialized later
|
||||
call initialize_prng()
|
||||
err = openmc_set_seed(seed)
|
||||
|
||||
! Read XML input files
|
||||
call read_input_xml()
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ module input_xml
|
|||
use nuclide_header
|
||||
use output, only: write_message, title, header, print_plot
|
||||
use plot_header
|
||||
use random_lcg, only: prn, seed, initialize_prng
|
||||
use random_lcg, only: prn, openmc_set_seed
|
||||
use surface_header
|
||||
use set_header, only: SetChar
|
||||
use settings
|
||||
|
|
@ -151,6 +151,7 @@ contains
|
|||
integer :: temp_int
|
||||
integer :: temp_int_array3(3)
|
||||
integer(C_INT32_T) :: i_start, i_end
|
||||
integer(C_INT64_T) :: seed
|
||||
integer(C_INT) :: err
|
||||
integer, allocatable :: temp_int_array(:)
|
||||
integer :: n_tracks
|
||||
|
|
@ -340,7 +341,7 @@ contains
|
|||
! Copy random number seed if specified
|
||||
if (check_for_node(root, "seed")) then
|
||||
call get_node_value(root, "seed", seed)
|
||||
call initialize_prng()
|
||||
err = openmc_set_seed(seed)
|
||||
end if
|
||||
|
||||
! Number of bins for logarithmic grid
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
module random_lcg
|
||||
|
||||
use, intrinsic :: ISO_C_BINDING
|
||||
|
||||
use constants
|
||||
|
||||
implicit none
|
||||
|
|
@ -7,28 +9,29 @@ module random_lcg
|
|||
private
|
||||
save
|
||||
|
||||
! Random number seed
|
||||
integer(8), public :: seed = 1_8
|
||||
! Starting seed
|
||||
integer(C_INT64_T), public, bind(C) :: seed = 1_8
|
||||
|
||||
integer(8) :: prn_seed0 ! original seed
|
||||
integer(8) :: prn_seed(N_STREAMS) ! current seed
|
||||
integer(8) :: prn_mult ! multiplication factor, g
|
||||
integer(8) :: prn_add ! additive factor, c
|
||||
integer :: prn_bits ! number of bits, M
|
||||
integer(8) :: prn_mod ! 2^M
|
||||
integer(8) :: prn_mask ! 2^M - 1
|
||||
integer(8) :: prn_stride ! stride between particles
|
||||
real(8) :: prn_norm ! 2^(-M)
|
||||
integer :: stream ! current RNG stream
|
||||
! LCG parameters
|
||||
integer(C_INT64_T), parameter :: prn_mult = 2806196910506780709_8 ! multiplication factor, g
|
||||
integer(C_INT64_T), parameter :: prn_add = 1_8 ! additive factor, c
|
||||
integer, parameter :: prn_bits = 63 ! number of bits, M
|
||||
integer(C_INT64_T), parameter :: prn_mod = ibset(0_8, prn_bits) ! 2^M
|
||||
integer(C_INT64_T), parameter :: prn_mask = not(prn_mod) ! 2^M - 1
|
||||
integer(C_INT64_T), parameter :: prn_stride = 152917_8 ! stride between particles
|
||||
real(C_DOUBLE), parameter :: prn_norm = 2._8**(-prn_bits) ! 2^(-M)
|
||||
|
||||
! Current PRNG state
|
||||
integer(C_INT64_T) :: prn_seed(N_STREAMS) ! current seed
|
||||
integer :: stream ! current RNG stream
|
||||
!$omp threadprivate(prn_seed, stream)
|
||||
|
||||
public :: prn
|
||||
public :: future_prn
|
||||
public :: initialize_prng
|
||||
public :: set_particle_seed
|
||||
public :: advance_prn_seed
|
||||
public :: prn_set_stream
|
||||
public :: openmc_set_seed
|
||||
|
||||
contains
|
||||
|
||||
|
|
@ -38,10 +41,10 @@ contains
|
|||
|
||||
function prn() result(pseudo_rn)
|
||||
|
||||
real(8) :: pseudo_rn
|
||||
real(C_DOUBLE) :: pseudo_rn
|
||||
|
||||
! This algorithm uses bit-masking to find the next integer(8) value to be
|
||||
! used to calculate the random number
|
||||
! This algorithm uses bit-masking to find the next integer(C_INT64_T) value
|
||||
! to be used to calculate the random number
|
||||
|
||||
prn_seed(stream) = iand(prn_mult*prn_seed(stream) + prn_add, prn_mask)
|
||||
|
||||
|
|
@ -59,40 +62,14 @@ contains
|
|||
|
||||
function future_prn(n) result(pseudo_rn)
|
||||
|
||||
integer(8), intent(in) :: n ! number of prns to skip
|
||||
integer(C_INT64_T), intent(in) :: n ! number of prns to skip
|
||||
|
||||
real(8) :: pseudo_rn
|
||||
real(C_DOUBLE) :: pseudo_rn
|
||||
|
||||
pseudo_rn = future_seed(n, prn_seed(stream)) * prn_norm
|
||||
|
||||
end function future_prn
|
||||
|
||||
!===============================================================================
|
||||
! INITIALIZE_PRNG sets up the random number generator, determining the seed and
|
||||
! values for g, c, and m.
|
||||
!===============================================================================
|
||||
|
||||
subroutine initialize_prng()
|
||||
|
||||
integer :: i
|
||||
|
||||
prn_seed0 = seed
|
||||
!$omp parallel
|
||||
do i = 1, N_STREAMS
|
||||
prn_seed(i) = prn_seed0 + i - 1
|
||||
end do
|
||||
stream = STREAM_TRACKING
|
||||
!$omp end parallel
|
||||
prn_mult = 2806196910506780709_8
|
||||
prn_add = 1_8
|
||||
prn_bits = 63
|
||||
prn_mod = ibset(0_8, prn_bits) ! clever way of calculating 2**bits
|
||||
prn_mask = prn_mod - 1_8
|
||||
prn_stride = 152917_8
|
||||
prn_norm = 2._8**(-prn_bits)
|
||||
|
||||
end subroutine initialize_prng
|
||||
|
||||
!===============================================================================
|
||||
! SET_PARTICLE_SEED sets the seed to a unique value based on the ID of the
|
||||
! particle
|
||||
|
|
@ -100,12 +77,12 @@ contains
|
|||
|
||||
subroutine set_particle_seed(id)
|
||||
|
||||
integer(8), intent(in) :: id
|
||||
integer(C_INT64_T), intent(in) :: id
|
||||
|
||||
integer :: i
|
||||
|
||||
do i = 1, N_STREAMS
|
||||
prn_seed(i) = future_seed(id*prn_stride, prn_seed0 + i - 1)
|
||||
prn_seed(i) = future_seed(id*prn_stride, seed + i - 1)
|
||||
end do
|
||||
|
||||
end subroutine set_particle_seed
|
||||
|
|
@ -117,7 +94,7 @@ contains
|
|||
|
||||
subroutine advance_prn_seed(n)
|
||||
|
||||
integer(8), intent(in) :: n ! number of seeds to skip
|
||||
integer(C_INT64_T), intent(in) :: n ! number of seeds to skip
|
||||
|
||||
prn_seed(stream) = future_seed(n, prn_seed(stream))
|
||||
|
||||
|
|
@ -132,15 +109,15 @@ contains
|
|||
|
||||
function future_seed(n, seed) result(new_seed)
|
||||
|
||||
integer(8), intent(in) :: n ! number of seeds to skip
|
||||
integer(8), intent(in) :: seed ! original seed
|
||||
integer(8) :: new_seed ! new seed
|
||||
integer(C_INT64_T), intent(in) :: n ! number of seeds to skip
|
||||
integer(C_INT64_T), intent(in) :: seed ! original seed
|
||||
integer(C_INT64_T) :: new_seed ! new seed
|
||||
|
||||
integer(8) :: nskip ! positive number of seeds to skip
|
||||
integer(8) :: g ! original multiplicative constant
|
||||
integer(8) :: c ! original additive constnat
|
||||
integer(8) :: g_new ! new effective multiplicative constant
|
||||
integer(8) :: c_new ! new effective additive constant
|
||||
integer(C_INT64_T) :: nskip ! positive number of seeds to skip
|
||||
integer(C_INT64_T) :: g ! original multiplicative constant
|
||||
integer(C_INT64_T) :: c ! original additive constnat
|
||||
integer(C_INT64_T) :: g_new ! new effective multiplicative constant
|
||||
integer(C_INT64_T) :: c_new ! new effective additive constant
|
||||
|
||||
! In cases where we want to skip backwards, we add the period of the random
|
||||
! number generator until the number of PRNs to skip is positive since
|
||||
|
|
@ -198,4 +175,26 @@ contains
|
|||
|
||||
end subroutine prn_set_stream
|
||||
|
||||
!===============================================================================
|
||||
! C API FUNCTIONS
|
||||
!===============================================================================
|
||||
|
||||
function openmc_set_seed(new_seed) result(err) bind(C)
|
||||
! Saves the starting seed and sets up the PRNG thread state
|
||||
integer(C_INT64_T), value, intent(in) :: new_seed
|
||||
integer(C_INT) :: err
|
||||
|
||||
integer :: i
|
||||
|
||||
err = 0
|
||||
seed = new_seed
|
||||
!$omp parallel
|
||||
do i = 1, N_STREAMS
|
||||
prn_seed(i) = seed + i - 1
|
||||
end do
|
||||
stream = STREAM_TRACKING
|
||||
!$omp end parallel
|
||||
|
||||
end function openmc_set_seed
|
||||
|
||||
end module random_lcg
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue