mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-26 21:25:36 -04:00
Merge pull request #993 from paulromano/capi-more
Add C API bindings for mesh creation
This commit is contained in:
commit
06161d1693
23 changed files with 755 additions and 234 deletions
|
|
@ -93,29 +93,13 @@ or ``multi-group``.
|
|||
|
||||
*Default*: continuous-energy
|
||||
|
||||
---------------------
|
||||
``<entropy>`` Element
|
||||
---------------------
|
||||
--------------------------
|
||||
``<entropy_mesh>`` Element
|
||||
--------------------------
|
||||
|
||||
The ``<entropy>`` element describes a mesh that is used for calculating Shannon
|
||||
entropy. This mesh should cover all possible fissionable materials in the
|
||||
problem. It has the following attributes/sub-elements:
|
||||
|
||||
:dimension:
|
||||
The number of mesh cells in the x, y, and z directions, respectively.
|
||||
|
||||
*Default*: If this tag is not present, the number of mesh cells is
|
||||
automatically determined by the code.
|
||||
|
||||
:lower_left:
|
||||
The Cartesian coordinates of the lower-left corner of the mesh.
|
||||
|
||||
*Default*: None
|
||||
|
||||
:upper_right:
|
||||
The Cartesian coordinates of the upper-right corner of the mesh.
|
||||
|
||||
*Default*: None
|
||||
The ``<entropy_mesh>`` element indicates the ID of a mesh that is to be used for
|
||||
calculating Shannon entropy. The mesh should cover all possible fissionable
|
||||
materials in the problem and is specified using a :ref:`mesh_element`.
|
||||
|
||||
-----------------------------------
|
||||
``<generations_per_batch>`` Element
|
||||
|
|
@ -199,6 +183,36 @@ then, OpenMC will only use up to the :math:`P_1` data.
|
|||
.. note:: This element is not used in the continuous-energy
|
||||
:ref:`energy_mode`.
|
||||
|
||||
.. _mesh_element:
|
||||
|
||||
------------------
|
||||
``<mesh>`` Element
|
||||
------------------
|
||||
|
||||
The ``<mesh>`` element describes a mesh that is used either for calculating
|
||||
Shannon entropy, applying the uniform fission site method, or in tallies. For
|
||||
Shannon entropy meshes, the mesh should cover all possible fissionable materials
|
||||
in the problem. It has the following attributes/sub-elements:
|
||||
|
||||
:id:
|
||||
A unique integer that is used to identify the mesh.
|
||||
|
||||
:dimension:
|
||||
The number of mesh cells in the x, y, and z directions, respectively.
|
||||
|
||||
*Default*: If this tag is not present, the number of mesh cells is
|
||||
automatically determined by the code.
|
||||
|
||||
:lower_left:
|
||||
The Cartesian coordinates of the lower-left corner of the mesh.
|
||||
|
||||
*Default*: None
|
||||
|
||||
:upper_right:
|
||||
The Cartesian coordinates of the upper-right corner of the mesh.
|
||||
|
||||
*Default*: None
|
||||
|
||||
-----------------------
|
||||
``<no_reduce>`` Element
|
||||
-----------------------
|
||||
|
|
@ -765,30 +779,15 @@ has the following attributes/sub-elements:
|
|||
|
||||
|
||||
------------------------
|
||||
``<uniform_fs>`` Element
|
||||
``<ufs_mesh>`` Element
|
||||
------------------------
|
||||
|
||||
The ``<uniform_fs>`` element describes a mesh that is used for re-weighting
|
||||
source sites at every generation based on the uniform fission site methodology
|
||||
described in Kelly et al., "MC21 Analysis of the Nuclear Energy Agency Monte
|
||||
Carlo Performance Benchmark Problem," Proceedings of *Physor 2012*, Knoxville,
|
||||
TN (2012). This mesh should cover all possible fissionable materials in the
|
||||
problem. It has the following attributes/sub-elements:
|
||||
|
||||
:dimension:
|
||||
The number of mesh cells in the x, y, and z directions, respectively.
|
||||
|
||||
*Default*: None
|
||||
|
||||
:lower_left:
|
||||
The Cartesian coordinates of the lower-left corner of the mesh.
|
||||
|
||||
*Default*: None
|
||||
|
||||
:upper_right:
|
||||
The Cartesian coordinates of the upper-right corner of the mesh.
|
||||
|
||||
*Default*: None
|
||||
The ``<ufs_mesh>`` element indicates the ID of a mesh that is used for
|
||||
re-weighting source sites at every generation based on the uniform fission site
|
||||
methodology described in Kelly et al., "MC21 Analysis of the Nuclear Energy
|
||||
Agency Monte Carlo Performance Benchmark Problem," Proceedings of *Physor 2012*,
|
||||
Knoxville, TN (2012). The mesh should cover all possible fissionable materials
|
||||
in the problem and is specified using a :ref:`mesh_element`.
|
||||
|
||||
.. _verbosity:
|
||||
|
||||
|
|
|
|||
|
|
@ -44,5 +44,8 @@ Classes
|
|||
EnergyFilter
|
||||
MaterialFilter
|
||||
Material
|
||||
Mesh
|
||||
MeshFilter
|
||||
MeshSurfaceFilter
|
||||
Nuclide
|
||||
Tally
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ extern "C" {
|
|||
int delayed_group;
|
||||
};
|
||||
|
||||
void openmc_calculate_voumes();
|
||||
void openmc_calculate_volumes();
|
||||
int openmc_cell_get_fill(int32_t index, int* type, int32_t** indices, int32_t* n);
|
||||
int openmc_cell_get_id(int32_t index, int32_t* id);
|
||||
int openmc_cell_set_fill(int32_t index, int type, int32_t n, const int32_t* indices);
|
||||
|
|
@ -27,10 +27,13 @@ extern "C" {
|
|||
int openmc_extend_cells(int32_t n, int32_t* index_start, int32_t* index_end);
|
||||
int openmc_extend_filters(int32_t n, int32_t* index_start, int32_t* index_end);
|
||||
int openmc_extend_materials(int32_t n, int32_t* index_start, int32_t* index_end);
|
||||
int openmc_extend_meshes(int32_t n, int32_t* index_start, int32_t* index_end);
|
||||
int openmc_extend_sources(int32_t n, int32_t* index_start, int32_t* index_end);
|
||||
int openmc_extend_tallies(int32_t n, int32_t* index_start, int32_t* index_end);
|
||||
int openmc_filter_get_id(int32_t index, int32_t* id);
|
||||
int openmc_filter_get_type(int32_t index, const char** type);
|
||||
int openmc_filter_set_id(int32_t index, int32_t id);
|
||||
int openmc_filter_set_type(int32_t index, const char* type);
|
||||
void openmc_finalize();
|
||||
int openmc_find(double* xyz, int rtype, int32_t* id, int32_t* instance);
|
||||
int openmc_get_cell_index(int32_t id, int32_t* index);
|
||||
|
|
@ -38,7 +41,9 @@ extern "C" {
|
|||
void openmc_get_filter_next_id(int32_t* id);
|
||||
int openmc_get_keff(double k_combined[]);
|
||||
int openmc_get_material_index(int32_t id, int32_t* index);
|
||||
int openmc_get_mesh_index(int32_t id, int32_t* index);
|
||||
int openmc_get_nuclide_index(const char name[], int* index);
|
||||
int64_t openmc_get_seed();
|
||||
int openmc_get_tally_index(int32_t id, int32_t* index);
|
||||
void openmc_hard_reset();
|
||||
void openmc_init(const int* intracomm);
|
||||
|
|
@ -53,13 +58,22 @@ extern "C" {
|
|||
int openmc_material_set_id(int32_t index, int32_t id);
|
||||
int openmc_material_filter_get_bins(int32_t index, int32_t** bins, int32_t* n);
|
||||
int openmc_material_filter_set_bins(int32_t index, int32_t n, const int32_t* bins);
|
||||
int openmc_mesh_filter_get_mesh(int32_t index, int32_t* index_mesh);
|
||||
int openmc_mesh_filter_set_mesh(int32_t index, int32_t index_mesh);
|
||||
int openmc_mesh_get_id(int32_t index, int32_t* id);
|
||||
int openmc_mesh_get_dimension(int32_t index, int** id, int* n);
|
||||
int openmc_mesh_get_params(int32_t index, double** ll, double** ur, double** width, int* n);
|
||||
int openmc_mesh_set_id(int32_t index, int32_t id);
|
||||
int openmc_mesh_set_dimension(int32_t index, int n, const int* dims);
|
||||
int openmc_mesh_set_params(int32_t index, const double* ll, const double* ur, const double* width, int n);
|
||||
int openmc_meshsurface_filter_get_mesh(int32_t index, int32_t* index_mesh);
|
||||
int openmc_meshsurface_filter_set_mesh(int32_t index, int32_t index_mesh);
|
||||
int openmc_next_batch();
|
||||
int openmc_next_batch(int* status);
|
||||
int openmc_nuclide_name(int index, char** name);
|
||||
void openmc_plot_geometry();
|
||||
void openmc_reset();
|
||||
void openmc_run();
|
||||
int openmc_run();
|
||||
void openmc_set_seed(int64_t new_seed);
|
||||
void openmc_simulation_finalize();
|
||||
void openmc_simulation_init();
|
||||
int openmc_source_bank(struct Bank** ptr, int64_t* n);
|
||||
|
|
@ -83,7 +97,8 @@ extern "C" {
|
|||
int openmc_tally_set_filters(int32_t index, int n, const int32_t* indices);
|
||||
int openmc_tally_set_id(int32_t index, int32_t id);
|
||||
int openmc_tally_set_nuclides(int32_t index, int n, const char** nuclides);
|
||||
int openmc_tally_set_scores(int32_t index, int n, const int* scores);
|
||||
int openmc_tally_set_scores(int32_t index, int n, const char** scores);
|
||||
int openmc_tally_set_type(int32_t index, const char* type);
|
||||
int openmc_zernike_filter_get_order(int32_t index, int* order);
|
||||
int openmc_zernike_filter_get_params(int32_t index, double* x, double* y, double* r);
|
||||
int openmc_zernike_filter_set_order(int32_t index, int order);
|
||||
|
|
@ -91,17 +106,17 @@ extern "C" {
|
|||
const double* y, const double* r);
|
||||
|
||||
// Error codes
|
||||
extern int E_UNASSIGNED;
|
||||
extern int E_ALLOCATE;
|
||||
extern int E_OUT_OF_BOUNDS;
|
||||
extern int E_INVALID_SIZE;
|
||||
extern int E_INVALID_ARGUMENT;
|
||||
extern int E_INVALID_TYPE;
|
||||
extern int E_INVALID_ID;
|
||||
extern int E_GEOMETRY;
|
||||
extern int E_DATA;
|
||||
extern int E_PHYSICS;
|
||||
extern int E_WARNING;
|
||||
extern int OPENMC_E_UNASSIGNED;
|
||||
extern int OPENMC_E_ALLOCATE;
|
||||
extern int OPENMC_E_OUT_OF_BOUNDS;
|
||||
extern int OPENMC_E_INVALID_SIZE;
|
||||
extern int OPENMC_E_INVALID_ARGUMENT;
|
||||
extern int OPENMC_E_INVALID_TYPE;
|
||||
extern int OPENMC_E_INVALID_ID;
|
||||
extern int OPENMC_E_GEOMETRY;
|
||||
extern int OPENMC_E_DATA;
|
||||
extern int OPENMC_E_PHYSICS;
|
||||
extern int OPENMC_E_WARNING;
|
||||
|
||||
// Global variables
|
||||
extern char openmc_err_msg[256];
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ from .core import *
|
|||
from .nuclide import *
|
||||
from .material import *
|
||||
from .cell import *
|
||||
from .mesh import *
|
||||
from .filter import *
|
||||
from .tally import *
|
||||
from .settings import settings
|
||||
|
|
|
|||
|
|
@ -5,9 +5,10 @@ from weakref import WeakValueDictionary
|
|||
import numpy as np
|
||||
from numpy.ctypeslib import as_array
|
||||
|
||||
from openmc.exceptions import AllocationError, InvalidIDError
|
||||
from . import _dll
|
||||
from .core import _FortranObjectWithID
|
||||
from .error import _error_handler, AllocationError, InvalidIDError
|
||||
from .error import _error_handler
|
||||
from .material import Material
|
||||
|
||||
__all__ = ['Cell', 'cells']
|
||||
|
|
@ -44,7 +45,7 @@ class Cell(_FortranObjectWithID):
|
|||
|
||||
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.
|
||||
:data:`openmc.capi.cells` mapping.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
|
@ -115,14 +116,15 @@ class Cell(_FortranObjectWithID):
|
|||
def fill(self, fill):
|
||||
if isinstance(fill, Iterable):
|
||||
n = len(fill)
|
||||
indices = (c_int*n)(*(m._index for m in fill))
|
||||
_dll.openmc_cell_set_fill(self._index, 1, 1, indices)
|
||||
indices = (c_int32*n)(*(m._index if m is not None else -1
|
||||
for m in fill))
|
||||
_dll.openmc_cell_set_fill(self._index, 1, n, indices)
|
||||
elif isinstance(fill, Material):
|
||||
materials = [fill]
|
||||
indices = (c_int*1)(fill._index)
|
||||
indices = (c_int32*1)(fill._index)
|
||||
_dll.openmc_cell_set_fill(self._index, 1, 1, indices)
|
||||
elif fill is None:
|
||||
indices = (c_int32*1)(-1)
|
||||
_dll.openmc_cell_set_fill(self._index, 1, 1, indices)
|
||||
else:
|
||||
raise NotImplementedError
|
||||
|
||||
def set_temperature(self, T, instance=None):
|
||||
"""Set the temperature of a cell
|
||||
|
|
|
|||
|
|
@ -6,8 +6,9 @@ from warnings import warn
|
|||
import numpy as np
|
||||
from numpy.ctypeslib import as_array
|
||||
|
||||
from openmc.exceptions import AllocationError
|
||||
from . import _dll
|
||||
from .error import _error_handler, AllocationError
|
||||
from .error import _error_handler
|
||||
import openmc.capi
|
||||
|
||||
|
||||
|
|
@ -31,9 +32,12 @@ _dll.openmc_init.restype = None
|
|||
_dll.openmc_get_keff.argtypes = [POINTER(c_double*2)]
|
||||
_dll.openmc_get_keff.restype = c_int
|
||||
_dll.openmc_get_keff.errcheck = _error_handler
|
||||
_dll.openmc_next_batch.argtypes = [POINTER(c_int)]
|
||||
_dll.openmc_next_batch.restype = c_int
|
||||
_dll.openmc_next_batch.errcheck = _error_handler
|
||||
_dll.openmc_plot_geometry.restype = None
|
||||
_dll.openmc_run.restype = None
|
||||
_dll.openmc_run.restype = c_int
|
||||
_dll.openmc_run.errcheck = _error_handler
|
||||
_dll.openmc_reset.restype = None
|
||||
_dll.openmc_source_bank.argtypes = [POINTER(POINTER(_Bank)), POINTER(c_int64)]
|
||||
_dll.openmc_source_bank.restype = c_int
|
||||
|
|
@ -147,13 +151,13 @@ def iter_batches():
|
|||
"""
|
||||
while True:
|
||||
# Run next batch
|
||||
retval = next_batch()
|
||||
status = next_batch()
|
||||
|
||||
# Provide opportunity for user to perform action between batches
|
||||
yield
|
||||
|
||||
# End the iteration
|
||||
if retval < 0:
|
||||
if status != 0:
|
||||
break
|
||||
|
||||
|
||||
|
|
@ -180,12 +184,18 @@ def keff():
|
|||
|
||||
|
||||
def next_batch():
|
||||
"""Run next batch."""
|
||||
retval = _dll.openmc_next_batch()
|
||||
if retval == -3:
|
||||
raise AllocationError('Simulation has not been initialized. You must call '
|
||||
'openmc.capi.simulation_init() first.')
|
||||
return retval
|
||||
"""Run next batch.
|
||||
|
||||
Returns
|
||||
-------
|
||||
int
|
||||
Status after running a batch (0=normal, 1=reached maximum number of
|
||||
batches, 2=tally triggers reached)
|
||||
|
||||
"""
|
||||
status = c_int()
|
||||
_dll.openmc_next_batch(status)
|
||||
return status.value
|
||||
|
||||
|
||||
def plot_geometry():
|
||||
|
|
|
|||
|
|
@ -1,45 +1,10 @@
|
|||
from ctypes import c_int, c_char
|
||||
from warnings import warn
|
||||
|
||||
import openmc.exceptions as exc
|
||||
from . import _dll
|
||||
|
||||
|
||||
class OpenMCError(Exception):
|
||||
"""Root exception class for OpenMC."""
|
||||
|
||||
|
||||
class GeometryError(OpenMCError):
|
||||
"""Geometry-related error"""
|
||||
|
||||
|
||||
class InvalidIDError(OpenMCError):
|
||||
"""Use of an ID that is invalid."""
|
||||
|
||||
|
||||
class AllocationError(OpenMCError):
|
||||
"""Error related to memory allocation."""
|
||||
|
||||
|
||||
class OutOfBoundsError(OpenMCError):
|
||||
"""Index in array out of bounds."""
|
||||
|
||||
|
||||
class DataError(OpenMCError):
|
||||
"""Error relating to nuclear data."""
|
||||
|
||||
|
||||
class PhysicsError(OpenMCError):
|
||||
"""Error relating to performing physics."""
|
||||
|
||||
|
||||
class InvalidArgumentError(OpenMCError):
|
||||
"""Argument passed was invalid."""
|
||||
|
||||
|
||||
class InvalidTypeError(OpenMCError):
|
||||
"""Tried to perform an operation on the wrong type."""
|
||||
|
||||
|
||||
def _error_handler(err, func, args):
|
||||
"""Raise exception according to error code."""
|
||||
|
||||
|
|
@ -52,23 +17,23 @@ def _error_handler(err, func, args):
|
|||
msg = errmsg.value.decode()
|
||||
|
||||
# Raise exception type corresponding to error code
|
||||
if err == errcode('e_allocate'):
|
||||
raise AllocationError(msg)
|
||||
elif err == errcode('e_out_of_bounds'):
|
||||
raise OutOfBoundsError(msg)
|
||||
elif err == errcode('e_invalid_argument'):
|
||||
raise InvalidArgumentError(msg)
|
||||
elif err == errcode('e_invalid_type'):
|
||||
raise InvalidTypeError(msg)
|
||||
if err == errcode('e_invalid_id'):
|
||||
raise InvalidIDError(msg)
|
||||
elif err == errcode('e_geometry'):
|
||||
raise GeometryError(msg)
|
||||
elif err == errcode('e_data'):
|
||||
raise DataError(msg)
|
||||
elif err == errcode('e_physics'):
|
||||
raise PhysicsError(msg)
|
||||
elif err == errcode('e_warning'):
|
||||
if err == errcode('OPENMC_E_ALLOCATE'):
|
||||
raise exc.AllocationError(msg)
|
||||
elif err == errcode('OPENMC_E_OUT_OF_BOUNDS'):
|
||||
raise exc.OutOfBoundsError(msg)
|
||||
elif err == errcode('OPENMC_E_INVALID_ARGUMENT'):
|
||||
raise exc.InvalidArgumentError(msg)
|
||||
elif err == errcode('OPENMC_E_INVALID_TYPE'):
|
||||
raise exc.InvalidTypeError(msg)
|
||||
if err == errcode('OPENMC_E_INVALID_ID'):
|
||||
raise exc.InvalidIDError(msg)
|
||||
elif err == errcode('OPENMC_E_GEOMETRY'):
|
||||
raise exc.GeometryError(msg)
|
||||
elif err == errcode('OPENMC_E_DATA'):
|
||||
raise exc.DataError(msg)
|
||||
elif err == errcode('OPENMC_E_PHYSICS'):
|
||||
raise exc.PhysicsError(msg)
|
||||
elif err == errcode('OPENMC_E_WARNING'):
|
||||
warn(msg)
|
||||
elif err < 0:
|
||||
raise OpenMCError("Unknown error encountered (code {}).".format(err))
|
||||
raise exc.OpenMCError("Unknown error encountered (code {}).".format(err))
|
||||
|
|
|
|||
|
|
@ -6,17 +6,19 @@ from weakref import WeakValueDictionary
|
|||
import numpy as np
|
||||
from numpy.ctypeslib import as_array
|
||||
|
||||
from openmc.exceptions import AllocationError, InvalidIDError
|
||||
from . import _dll
|
||||
from .core import _FortranObjectWithID
|
||||
from .error import _error_handler, AllocationError, InvalidIDError
|
||||
from .error import _error_handler
|
||||
from .material import Material
|
||||
from .mesh import Mesh
|
||||
|
||||
|
||||
__all__ = ['Filter', 'AzimuthalFilter', 'CellFilter',
|
||||
'CellbornFilter', 'CellfromFilter', 'DistribcellFilter',
|
||||
'DelayedGroupFilter', 'EnergyFilter', 'EnergyoutFilter',
|
||||
'EnergyFunctionFilter', 'MaterialFilter', 'MeshFilter',
|
||||
'MuFilter', 'PolarFilter', 'SurfaceFilter',
|
||||
'MeshSurfaceFilter', 'MuFilter', 'PolarFilter', 'SurfaceFilter',
|
||||
'UniverseFilter', 'filters']
|
||||
|
||||
# Tally functions
|
||||
|
|
@ -52,9 +54,15 @@ _dll.openmc_material_filter_get_bins.errcheck = _error_handler
|
|||
_dll.openmc_material_filter_set_bins.argtypes = [c_int32, c_int32, POINTER(c_int32)]
|
||||
_dll.openmc_material_filter_set_bins.restype = c_int
|
||||
_dll.openmc_material_filter_set_bins.errcheck = _error_handler
|
||||
_dll.openmc_mesh_filter_get_mesh.argtypes = [c_int32, POINTER(c_int32)]
|
||||
_dll.openmc_mesh_filter_get_mesh.restype = c_int
|
||||
_dll.openmc_mesh_filter_get_mesh.errcheck = _error_handler
|
||||
_dll.openmc_mesh_filter_set_mesh.argtypes = [c_int32, c_int32]
|
||||
_dll.openmc_mesh_filter_set_mesh.restype = c_int
|
||||
_dll.openmc_mesh_filter_set_mesh.errcheck = _error_handler
|
||||
_dll.openmc_meshsurface_filter_get_mesh.argtypes = [c_int32, POINTER(c_int32)]
|
||||
_dll.openmc_meshsurface_filter_get_mesh.restype = c_int
|
||||
_dll.openmc_meshsurface_filter_get_mesh.errcheck = _error_handler
|
||||
_dll.openmc_meshsurface_filter_set_mesh.argtypes = [c_int32, c_int32]
|
||||
_dll.openmc_meshsurface_filter_set_mesh.restype = c_int
|
||||
_dll.openmc_meshsurface_filter_set_mesh.errcheck = _error_handler
|
||||
|
|
@ -190,10 +198,40 @@ class MaterialFilter(Filter):
|
|||
class MeshFilter(Filter):
|
||||
filter_type = 'mesh'
|
||||
|
||||
def __init__(self, mesh=None, uid=None, new=True, index=None):
|
||||
super().__init__(uid, new, index)
|
||||
if mesh is not None:
|
||||
self.mesh = mesh
|
||||
|
||||
@property
|
||||
def mesh(self):
|
||||
index_mesh = c_int32()
|
||||
_dll.openmc_mesh_filter_get_mesh(self._index, index_mesh)
|
||||
return Mesh(index=index_mesh.value)
|
||||
|
||||
@mesh.setter
|
||||
def mesh(self, mesh):
|
||||
_dll.openmc_mesh_filter_set_mesh(self._index, mesh._index)
|
||||
|
||||
|
||||
class MeshSurfaceFilter(Filter):
|
||||
filter_type = 'meshsurface'
|
||||
|
||||
def __init__(self, mesh=None, uid=None, new=True, index=None):
|
||||
super().__init__(uid, new, index)
|
||||
if mesh is not None:
|
||||
self.mesh = mesh
|
||||
|
||||
@property
|
||||
def mesh(self):
|
||||
index_mesh = c_int32()
|
||||
_dll.openmc_meshsurface_filter_get_mesh(self._index, index_mesh)
|
||||
return Mesh(index=index_mesh.value)
|
||||
|
||||
@mesh.setter
|
||||
def mesh(self, mesh):
|
||||
_dll.openmc_meshsurface_filter_set_mesh(self._index, mesh._index)
|
||||
|
||||
|
||||
class MuFilter(Filter):
|
||||
filter_type = 'mu'
|
||||
|
|
|
|||
|
|
@ -5,9 +5,10 @@ from weakref import WeakValueDictionary
|
|||
import numpy as np
|
||||
from numpy.ctypeslib import as_array
|
||||
|
||||
from openmc.exceptions import AllocationError, InvalidIDError
|
||||
from . import _dll, Nuclide
|
||||
from .core import _FortranObjectWithID
|
||||
from .error import _error_handler, AllocationError, InvalidIDError
|
||||
from .error import _error_handler
|
||||
|
||||
|
||||
__all__ = ['Material', 'materials']
|
||||
|
|
@ -89,6 +90,9 @@ class Material(_FortranObjectWithID):
|
|||
index = index.value
|
||||
else:
|
||||
index = mapping[uid]._index
|
||||
elif index == -1:
|
||||
# Special value indicates void material
|
||||
return None
|
||||
|
||||
if index not in cls.__instances:
|
||||
instance = super(Material, cls).__new__(cls)
|
||||
|
|
|
|||
183
openmc/capi/mesh.py
Normal file
183
openmc/capi/mesh.py
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
from collections.abc import Mapping, Iterable
|
||||
from ctypes import c_int, c_int32, c_double, POINTER
|
||||
from weakref import WeakValueDictionary
|
||||
|
||||
import numpy as np
|
||||
from numpy.ctypeslib import as_array
|
||||
|
||||
from openmc.exceptions import AllocationError, InvalidIDError
|
||||
from . import _dll
|
||||
from .core import _FortranObjectWithID
|
||||
from .error import _error_handler
|
||||
from .material import Material
|
||||
|
||||
__all__ = ['Mesh', 'meshes']
|
||||
|
||||
# Mesh functions
|
||||
_dll.openmc_extend_meshes.argtypes = [c_int32, POINTER(c_int32), POINTER(c_int32)]
|
||||
_dll.openmc_extend_meshes.restype = c_int
|
||||
_dll.openmc_extend_meshes.errcheck = _error_handler
|
||||
_dll.openmc_mesh_get_id.argtypes = [c_int32, POINTER(c_int32)]
|
||||
_dll.openmc_mesh_get_id.restype = c_int
|
||||
_dll.openmc_mesh_get_id.errcheck = _error_handler
|
||||
_dll.openmc_mesh_get_dimension.argtypes = [c_int32, POINTER(POINTER(c_int)), POINTER(c_int)]
|
||||
_dll.openmc_mesh_get_dimension.restype = c_int
|
||||
_dll.openmc_mesh_get_dimension.errcheck = _error_handler
|
||||
_dll.openmc_mesh_get_params.argtypes = [
|
||||
c_int32, POINTER(POINTER(c_double)), POINTER(POINTER(c_double)),
|
||||
POINTER(POINTER(c_double)), POINTER(c_int)]
|
||||
_dll.openmc_mesh_get_params.restype = c_int
|
||||
_dll.openmc_mesh_get_params.errcheck = _error_handler
|
||||
_dll.openmc_mesh_set_id.argtypes = [c_int32, c_int32]
|
||||
_dll.openmc_mesh_set_id.restype = c_int
|
||||
_dll.openmc_mesh_set_id.errcheck = _error_handler
|
||||
_dll.openmc_mesh_set_dimension.argtypes = [c_int32, c_int, POINTER(c_int)]
|
||||
_dll.openmc_mesh_set_dimension.restype = c_int
|
||||
_dll.openmc_mesh_set_dimension.errcheck = _error_handler
|
||||
_dll.openmc_mesh_set_params.argtypes = [
|
||||
c_int32, c_int, POINTER(c_double), POINTER(c_double), POINTER(c_double)]
|
||||
_dll.openmc_mesh_set_params.restype = c_int
|
||||
_dll.openmc_mesh_set_params.errcheck = _error_handler
|
||||
_dll.openmc_get_mesh_index.argtypes = [c_int32, POINTER(c_int32)]
|
||||
_dll.openmc_get_mesh_index.restype = c_int
|
||||
_dll.openmc_get_mesh_index.errcheck = _error_handler
|
||||
|
||||
|
||||
class Mesh(_FortranObjectWithID):
|
||||
"""Mesh stored internally.
|
||||
|
||||
This class exposes a mesh that is stored internally in the OpenMC
|
||||
library. To obtain a view of a mesh with a given ID, use the
|
||||
:data:`openmc.capi.meshes` mapping.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
index : int
|
||||
Index in the `meshes` array.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
id : int
|
||||
ID of the mesh
|
||||
dimension : iterable of int
|
||||
The number of mesh cells in each direction.
|
||||
lower_left : numpy.ndarray
|
||||
The lower-left corner of the structured mesh. If only two coordinate are
|
||||
given, it is assumed that the mesh is an x-y mesh.
|
||||
upper_right : numpy.ndarray
|
||||
The upper-right corner of the structrued mesh. If only two coordinate
|
||||
are given, it is assumed that the mesh is an x-y mesh.
|
||||
width : numpy.ndarray
|
||||
The width of mesh cells in each direction.
|
||||
|
||||
"""
|
||||
__instances = WeakValueDictionary()
|
||||
|
||||
def __new__(cls, uid=None, new=True, index=None):
|
||||
mapping = meshes
|
||||
if index is None:
|
||||
if new:
|
||||
# Determine ID to assign
|
||||
if uid is None:
|
||||
uid = max(mapping, default=0) + 1
|
||||
else:
|
||||
if uid in mapping:
|
||||
raise AllocationError('A mesh with ID={} has already '
|
||||
'been allocated.'.format(uid))
|
||||
|
||||
index = c_int32()
|
||||
_dll.openmc_extend_meshes(1, index, None)
|
||||
index = index.value
|
||||
else:
|
||||
index = mapping[uid]._index
|
||||
|
||||
if index not in cls.__instances:
|
||||
instance = super().__new__(cls)
|
||||
instance._index = index
|
||||
if uid is not None:
|
||||
instance.id = uid
|
||||
cls.__instances[index] = instance
|
||||
|
||||
return cls.__instances[index]
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
mesh_id = c_int32()
|
||||
_dll.openmc_mesh_get_id(self._index, mesh_id)
|
||||
return mesh_id.value
|
||||
|
||||
@id.setter
|
||||
def id(self, mesh_id):
|
||||
_dll.openmc_mesh_set_id(self._index, mesh_id)
|
||||
|
||||
@property
|
||||
def dimension(self):
|
||||
dims = POINTER(c_int)()
|
||||
n = c_int()
|
||||
_dll.openmc_mesh_get_dimension(self._index, dims, n)
|
||||
return tuple(as_array(dims, (n.value,)))
|
||||
|
||||
@dimension.setter
|
||||
def dimension(self, dimension):
|
||||
n = len(dimension)
|
||||
dimension = (c_int*n)(*dimension)
|
||||
_dll.openmc_mesh_set_dimension(self._index, n, dimension)
|
||||
|
||||
@property
|
||||
def lower_left(self):
|
||||
return self._get_parameters()[0]
|
||||
|
||||
@property
|
||||
def upper_right(self):
|
||||
return self._get_parameters()[1]
|
||||
|
||||
@property
|
||||
def width(self):
|
||||
return self._get_parameters()[2]
|
||||
|
||||
def _get_parameters(self):
|
||||
ll = POINTER(c_double)()
|
||||
ur = POINTER(c_double)()
|
||||
w = POINTER(c_double)()
|
||||
n = c_int()
|
||||
_dll.openmc_mesh_get_params(self._index, ll, ur, w, n)
|
||||
return (
|
||||
as_array(ll, (n.value,)),
|
||||
as_array(ur, (n.value,)),
|
||||
as_array(w, (n.value,))
|
||||
)
|
||||
|
||||
def set_parameters(self, lower_left=None, upper_right=None, width=None):
|
||||
if lower_left is not None:
|
||||
n = len(lower_left)
|
||||
lower_left = (c_double*n)(*lower_left)
|
||||
if upper_right is not None:
|
||||
n = len(upper_right)
|
||||
upper_right = (c_double*n)(*upper_right)
|
||||
if width is not None:
|
||||
n = len(width)
|
||||
width = (c_double*n)(*width)
|
||||
_dll.openmc_mesh_set_params(self._index, n, lower_left, upper_right, width)
|
||||
|
||||
|
||||
class _MeshMapping(Mapping):
|
||||
def __getitem__(self, key):
|
||||
index = c_int32()
|
||||
try:
|
||||
_dll.openmc_get_mesh_index(key, index)
|
||||
except (AllocationError, InvalidIDError) as e:
|
||||
# __contains__ expects a KeyError to work correctly
|
||||
raise KeyError(str(e))
|
||||
return Mesh(index=index.value)
|
||||
|
||||
def __iter__(self):
|
||||
for i in range(len(self)):
|
||||
yield Mesh(index=i + 1).id
|
||||
|
||||
def __len__(self):
|
||||
return c_int32.in_dll(_dll, 'n_meshes').value
|
||||
|
||||
def __repr__(self):
|
||||
return repr(dict(self))
|
||||
|
||||
meshes = _MeshMapping()
|
||||
|
|
@ -5,9 +5,10 @@ from weakref import WeakValueDictionary
|
|||
import numpy as np
|
||||
from numpy.ctypeslib import as_array
|
||||
|
||||
from openmc.exceptions import DataError, AllocationError
|
||||
from . import _dll
|
||||
from .core import _FortranObject
|
||||
from .error import _error_handler, DataError, AllocationError
|
||||
from .error import _error_handler
|
||||
|
||||
|
||||
__all__ = ['Nuclide', 'nuclides', 'load_nuclide']
|
||||
|
|
|
|||
|
|
@ -6,10 +6,11 @@ import numpy as np
|
|||
from numpy.ctypeslib import as_array
|
||||
import scipy.stats
|
||||
|
||||
from openmc.exceptions import AllocationError, InvalidIDError
|
||||
from openmc.data.reaction import REACTION_NAME
|
||||
from . import _dll, Nuclide
|
||||
from .core import _FortranObjectWithID
|
||||
from .error import _error_handler, AllocationError, InvalidIDError
|
||||
from .error import _error_handler
|
||||
from .filter import _get_filter
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -23,9 +23,14 @@ class DataLibrary(EqualityMixin):
|
|||
def __init__(self):
|
||||
self.libraries = []
|
||||
|
||||
def get_by_material(self, value):
|
||||
def get_by_material(self, name):
|
||||
"""Return the library dictionary containing a given material.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name : str
|
||||
Name of material, e.g. 'Am241'
|
||||
|
||||
Returns
|
||||
-------
|
||||
library : dict or None
|
||||
|
|
@ -34,7 +39,7 @@ class DataLibrary(EqualityMixin):
|
|||
|
||||
"""
|
||||
for library in self.libraries:
|
||||
if value in library['materials']:
|
||||
if name in library['materials']:
|
||||
return library
|
||||
return None
|
||||
|
||||
|
|
|
|||
38
openmc/exceptions.py
Normal file
38
openmc/exceptions.py
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
class OpenMCError(Exception):
|
||||
"""Root exception class for OpenMC."""
|
||||
|
||||
|
||||
class GeometryError(OpenMCError):
|
||||
"""Geometry-related error"""
|
||||
|
||||
|
||||
class InvalidIDError(OpenMCError):
|
||||
"""Use of an ID that is invalid."""
|
||||
|
||||
|
||||
class AllocationError(OpenMCError):
|
||||
"""Error related to memory allocation."""
|
||||
|
||||
|
||||
class OutOfBoundsError(OpenMCError):
|
||||
"""Index in array out of bounds."""
|
||||
|
||||
|
||||
class DataError(OpenMCError):
|
||||
"""Error relating to nuclear data."""
|
||||
|
||||
|
||||
class PhysicsError(OpenMCError):
|
||||
"""Error relating to performing physics."""
|
||||
|
||||
|
||||
class InvalidArgumentError(OpenMCError):
|
||||
"""Argument passed was invalid."""
|
||||
|
||||
|
||||
class InvalidTypeError(OpenMCError):
|
||||
"""Tried to perform an operation on the wrong type."""
|
||||
|
||||
|
||||
class SetupError(OpenMCError):
|
||||
"""Error while setting up a problem."""
|
||||
|
|
@ -278,7 +278,7 @@ contains
|
|||
m % id = i_start
|
||||
|
||||
! Set mesh type to rectangular
|
||||
m % type = LATTICE_RECT
|
||||
m % type = MESH_REGULAR
|
||||
|
||||
! Get pointer to mesh XML node
|
||||
node_mesh = root % child("mesh")
|
||||
|
|
|
|||
|
|
@ -15,19 +15,19 @@ module error
|
|||
public :: write_message
|
||||
|
||||
! Error codes
|
||||
integer(C_INT), public, bind(C) :: E_UNASSIGNED = -1
|
||||
integer(C_INT), public, bind(C) :: E_ALLOCATE = -2
|
||||
integer(C_INT), public, bind(C) :: E_OUT_OF_BOUNDS = -3
|
||||
integer(C_INT), public, bind(C) :: E_INVALID_SIZE = -4
|
||||
integer(C_INT), public, bind(C) :: E_INVALID_ARGUMENT = -5
|
||||
integer(C_INT), public, bind(C) :: E_INVALID_TYPE = -6
|
||||
integer(C_INT), public, bind(C) :: E_INVALID_ID = -7
|
||||
integer(C_INT), public, bind(C) :: E_GEOMETRY = -8
|
||||
integer(C_INT), public, bind(C) :: E_DATA = -9
|
||||
integer(C_INT), public, bind(C) :: E_PHYSICS = -10
|
||||
integer(C_INT), public, bind(C, name='OPENMC_E_UNASSIGNED') :: E_UNASSIGNED = -1
|
||||
integer(C_INT), public, bind(C, name='OPENMC_E_ALLOCATE') :: E_ALLOCATE = -2
|
||||
integer(C_INT), public, bind(C, name='OPENMC_E_OUT_OF_BOUNDS') :: E_OUT_OF_BOUNDS = -3
|
||||
integer(C_INT), public, bind(C, name='OPENMC_E_INVALID_SIZE') :: E_INVALID_SIZE = -4
|
||||
integer(C_INT), public, bind(C, name='OPENMC_E_INVALID_ARGUMENT') :: E_INVALID_ARGUMENT = -5
|
||||
integer(C_INT), public, bind(C, name='OPENMC_E_INVALID_TYPE') :: E_INVALID_TYPE = -6
|
||||
integer(C_INT), public, bind(C, name='OPENMC_E_INVALID_ID') :: E_INVALID_ID = -7
|
||||
integer(C_INT), public, bind(C, name='OPENMC_E_GEOMETRY') :: E_GEOMETRY = -8
|
||||
integer(C_INT), public, bind(C, name='OPENMC_E_DATA') :: E_DATA = -9
|
||||
integer(C_INT), public, bind(C, name='OPENMC_E_PHYSICS') :: E_PHYSICS = -10
|
||||
|
||||
! Warning codes
|
||||
integer(C_INT), public, bind(C) :: E_WARNING = 1
|
||||
integer(C_INT), public, bind(C, name='OPENMC_E_WARNING') :: E_WARNING = 1
|
||||
|
||||
! Error message
|
||||
character(kind=C_CHAR), public, bind(C) :: openmc_err_msg(256)
|
||||
|
|
|
|||
|
|
@ -544,16 +544,12 @@ contains
|
|||
c % type = FILL_MATERIAL
|
||||
do i = 1, n
|
||||
j = indices(i)
|
||||
if (j == 0) then
|
||||
c % material(i) = MATERIAL_VOID
|
||||
if ((j >= 1 .and. j <= n_materials) .or. j == MATERIAL_VOID) then
|
||||
c % material(i) = j
|
||||
else
|
||||
if (j >= 1 .and. j <= n_materials) then
|
||||
c % material(i) = j
|
||||
else
|
||||
err = E_OUT_OF_BOUNDS
|
||||
call set_errmsg("Index " // trim(to_str(j)) // " in the &
|
||||
&materials array is out of bounds.")
|
||||
end if
|
||||
err = E_OUT_OF_BOUNDS
|
||||
call set_errmsg("Index " // trim(to_str(j)) // " in the &
|
||||
&materials array is out of bounds.")
|
||||
end if
|
||||
end do
|
||||
case (FILL_UNIVERSE)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
program main
|
||||
|
||||
use, intrinsic :: ISO_C_BINDING
|
||||
|
||||
use constants
|
||||
use message_passing
|
||||
use openmc_api, only: openmc_init, openmc_finalize, openmc_run, &
|
||||
|
|
@ -9,6 +11,7 @@ program main
|
|||
|
||||
implicit none
|
||||
|
||||
integer(C_INT) :: err
|
||||
#ifdef OPENMC_MPI
|
||||
integer :: mpi_err ! MPI error code
|
||||
#endif
|
||||
|
|
@ -27,7 +30,7 @@ program main
|
|||
! start problem based on mode
|
||||
select case (run_mode)
|
||||
case (MODE_FIXEDSOURCE, MODE_EIGENVALUE)
|
||||
call openmc_run()
|
||||
err = openmc_run()
|
||||
case (MODE_PLOTTING)
|
||||
call openmc_plot_geometry()
|
||||
case (MODE_PARTICLE)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ module mesh_header
|
|||
|
||||
use constants
|
||||
use dict_header, only: DictIntInt
|
||||
use error, only: warning, fatal_error
|
||||
use error
|
||||
use hdf5_interface
|
||||
use string, only: to_str, to_lower
|
||||
use xml_interface
|
||||
|
|
@ -15,6 +15,13 @@ module mesh_header
|
|||
private
|
||||
public :: free_memory_mesh
|
||||
public :: openmc_extend_meshes
|
||||
public :: openmc_get_mesh_index
|
||||
public :: openmc_mesh_get_id
|
||||
public :: openmc_mesh_get_dimension
|
||||
public :: openmc_mesh_get_params
|
||||
public :: openmc_mesh_set_id
|
||||
public :: openmc_mesh_set_dimension
|
||||
public :: openmc_mesh_set_params
|
||||
|
||||
!===============================================================================
|
||||
! STRUCTUREDMESH represents a tessellation of n-dimensional Euclidean space by
|
||||
|
|
@ -23,13 +30,13 @@ module mesh_header
|
|||
|
||||
type, public :: RegularMesh
|
||||
integer :: id = -1 ! user-specified id
|
||||
integer :: type ! rectangular, hexagonal
|
||||
integer :: n_dimension ! rank of mesh
|
||||
integer :: type = MESH_REGULAR ! rectangular, hexagonal
|
||||
integer(C_INT) :: n_dimension ! rank of mesh
|
||||
real(8) :: volume_frac ! volume fraction of each cell
|
||||
integer, allocatable :: dimension(:) ! number of cells in each direction
|
||||
real(8), allocatable :: lower_left(:) ! lower-left corner of mesh
|
||||
real(8), allocatable :: upper_right(:) ! upper-right corner of mesh
|
||||
real(8), allocatable :: width(:) ! width of each mesh cell
|
||||
integer(C_INT), allocatable :: dimension(:) ! number of cells in each direction
|
||||
real(C_DOUBLE), allocatable :: lower_left(:) ! lower-left corner of mesh
|
||||
real(C_DOUBLE), allocatable :: upper_right(:) ! upper-right corner of mesh
|
||||
real(C_DOUBLE), allocatable :: width(:) ! width of each mesh cell
|
||||
contains
|
||||
procedure :: from_xml => regular_from_xml
|
||||
procedure :: get_bin => regular_get_bin
|
||||
|
|
@ -592,4 +599,180 @@ contains
|
|||
err = 0
|
||||
end function openmc_extend_meshes
|
||||
|
||||
|
||||
function openmc_get_mesh_index(id, index) result(err) bind(C)
|
||||
! Return the index in the meshes array of a mesh with a given ID
|
||||
integer(C_INT32_T), value :: id
|
||||
integer(C_INT32_T), intent(out) :: index
|
||||
integer(C_INT) :: err
|
||||
|
||||
if (allocated(meshes)) then
|
||||
if (mesh_dict % has(id)) then
|
||||
index = mesh_dict % get(id)
|
||||
err = 0
|
||||
else
|
||||
err = E_INVALID_ID
|
||||
call set_errmsg("No mesh exists with ID=" // trim(to_str(id)) // ".")
|
||||
end if
|
||||
else
|
||||
err = E_ALLOCATE
|
||||
call set_errmsg("Memory has not been allocated for meshes.")
|
||||
end if
|
||||
end function openmc_get_mesh_index
|
||||
|
||||
|
||||
function openmc_mesh_get_id(index, id) result(err) bind(C)
|
||||
! Return the ID of a mesh
|
||||
integer(C_INT32_T), value :: index
|
||||
integer(C_INT32_T), intent(out) :: id
|
||||
integer(C_INT) :: err
|
||||
|
||||
if (index >= 1 .and. index <= size(meshes)) then
|
||||
id = meshes(index) % id
|
||||
err = 0
|
||||
else
|
||||
err = E_OUT_OF_BOUNDS
|
||||
call set_errmsg("Index in meshes array is out of bounds.")
|
||||
end if
|
||||
end function openmc_mesh_get_id
|
||||
|
||||
|
||||
function openmc_mesh_set_id(index, id) result(err) bind(C)
|
||||
! Set the ID of a mesh
|
||||
integer(C_INT32_T), value, intent(in) :: index
|
||||
integer(C_INT32_T), value, intent(in) :: id
|
||||
integer(C_INT) :: err
|
||||
|
||||
if (index >= 1 .and. index <= n_meshes) then
|
||||
meshes(index) % id = id
|
||||
call mesh_dict % set(id, index)
|
||||
err = 0
|
||||
else
|
||||
err = E_OUT_OF_BOUNDS
|
||||
call set_errmsg("Index in meshes array is out of bounds.")
|
||||
end if
|
||||
end function openmc_mesh_set_id
|
||||
|
||||
|
||||
function openmc_mesh_get_dimension(index, dims, n) result(err) bind(C)
|
||||
! Get the dimension of a mesh
|
||||
integer(C_INT32_T), value, intent(in) :: index
|
||||
type(C_PTR), intent(out) :: dims
|
||||
integer(C_INT), intent(out) :: n
|
||||
integer(C_INT) :: err
|
||||
|
||||
if (index >= 1 .and. index <= n_meshes) then
|
||||
dims = C_LOC(meshes(index) % dimension)
|
||||
n = meshes(index) % n_dimension
|
||||
err = 0
|
||||
else
|
||||
err = E_OUT_OF_BOUNDS
|
||||
call set_errmsg("Index in meshes array is out of bounds.")
|
||||
end if
|
||||
end function openmc_mesh_get_dimension
|
||||
|
||||
|
||||
function openmc_mesh_set_dimension(index, n, dims) result(err) bind(C)
|
||||
! Set the dimension of a mesh
|
||||
integer(C_INT32_T), value, intent(in) :: index
|
||||
integer(C_INT), value, intent(in) :: n
|
||||
integer(C_INT), intent(in) :: dims(n)
|
||||
integer(C_INT) :: err
|
||||
|
||||
if (index >= 1 .and. index <= n_meshes) then
|
||||
associate (m => meshes(index))
|
||||
if (allocated(m % dimension)) deallocate (m % dimension)
|
||||
if (allocated(m % lower_left)) deallocate (m % lower_left)
|
||||
if (allocated(m % upper_right)) deallocate (m % upper_right)
|
||||
if (allocated(m % width)) deallocate (m % width)
|
||||
|
||||
m % n_dimension = n
|
||||
allocate(m % dimension(n))
|
||||
allocate(m % lower_left(n))
|
||||
allocate(m % upper_right(n))
|
||||
allocate(m % width(n))
|
||||
|
||||
! Copy dimension
|
||||
m % dimension(:) = dims
|
||||
end associate
|
||||
err = 0
|
||||
else
|
||||
err = E_OUT_OF_BOUNDS
|
||||
call set_errmsg("Index in meshes array is out of bounds.")
|
||||
end if
|
||||
end function openmc_mesh_set_dimension
|
||||
|
||||
|
||||
function openmc_mesh_get_params(index, ll, ur, width, n) result(err) bind(C)
|
||||
! Get the mesh parameters
|
||||
integer(C_INT32_T), value, intent(in) :: index
|
||||
type(C_PTR), intent(out) :: ll
|
||||
type(C_PTR), intent(out) :: ur
|
||||
type(C_PTR), intent(out) :: width
|
||||
integer(C_INT), intent(out) :: n
|
||||
integer(C_INT) :: err
|
||||
|
||||
err = 0
|
||||
if (index >= 1 .and. index <= n_meshes) then
|
||||
associate (m => meshes(index))
|
||||
if (allocated(m % lower_left)) then
|
||||
ll = C_LOC(m % lower_left(1))
|
||||
ur = C_LOC(m % upper_right(1))
|
||||
width = C_LOC(m % width(1))
|
||||
n = m % n_dimension
|
||||
else
|
||||
err = E_ALLOCATE
|
||||
call set_errmsg("Mesh parameters have not been set.")
|
||||
end if
|
||||
end associate
|
||||
else
|
||||
err = E_OUT_OF_BOUNDS
|
||||
call set_errmsg("Index in meshes array is out of bounds.")
|
||||
end if
|
||||
end function openmc_mesh_get_params
|
||||
|
||||
|
||||
function openmc_mesh_set_params(index, n, ll, ur, width) result(err) bind(C)
|
||||
! Set the mesh parameters
|
||||
integer(C_INT32_T), value, intent(in) :: index
|
||||
integer(C_INT), value, intent(in) :: n
|
||||
real(C_DOUBLE), intent(in), optional :: ll(n)
|
||||
real(C_DOUBLE), intent(in), optional :: ur(n)
|
||||
real(C_DOUBLE), intent(in), optional :: width(n)
|
||||
integer(C_INT) :: err
|
||||
|
||||
err = 0
|
||||
if (index >= 1 .and. index <= n_meshes) then
|
||||
associate (m => meshes(index))
|
||||
if (allocated(m % lower_left)) deallocate (m % lower_left)
|
||||
if (allocated(m % upper_right)) deallocate (m % upper_right)
|
||||
if (allocated(m % width)) deallocate (m % width)
|
||||
|
||||
allocate(m % lower_left(n))
|
||||
allocate(m % upper_right(n))
|
||||
allocate(m % width(n))
|
||||
|
||||
if (present(ll) .and. present(ur)) then
|
||||
m % lower_left(:) = ll
|
||||
m % upper_right(:) = ur
|
||||
m % width(:) = (ur - ll) / m % dimension
|
||||
elseif (present(ll) .and. present(width)) then
|
||||
m % lower_left(:) = ll
|
||||
m % width(:) = width
|
||||
m % upper_right(:) = ll + width * m % dimension
|
||||
elseif (present(ur) .and. present(width)) then
|
||||
m % upper_right(:) = ur
|
||||
m % width(:) = width
|
||||
m % lower_left(:) = ur - width * m % dimension
|
||||
else
|
||||
err = E_INVALID_ARGUMENT
|
||||
call set_errmsg("At least two parameters must be specified.")
|
||||
end if
|
||||
end associate
|
||||
else
|
||||
err = E_OUT_OF_BOUNDS
|
||||
call set_errmsg("Index in meshes array is out of bounds.")
|
||||
end if
|
||||
end function openmc_mesh_set_params
|
||||
|
||||
end module mesh_header
|
||||
|
|
|
|||
|
|
@ -48,6 +48,10 @@ module simulation
|
|||
public :: openmc_simulation_init
|
||||
public :: openmc_simulation_finalize
|
||||
|
||||
integer(C_INT), parameter :: STATUS_EXIT_NORMAL = 0
|
||||
integer(C_INT), parameter :: STATUS_EXIT_MAX_BATCH = 1
|
||||
integer(C_INT), parameter :: STATUS_EXIT_ON_TRIGGER = 2
|
||||
|
||||
contains
|
||||
|
||||
!===============================================================================
|
||||
|
|
@ -56,28 +60,36 @@ contains
|
|||
! calculation.
|
||||
!===============================================================================
|
||||
|
||||
subroutine openmc_run() bind(C)
|
||||
function openmc_run() result(err) bind(C)
|
||||
integer(C_INT) :: err
|
||||
integer(C_INT) :: status
|
||||
|
||||
call openmc_simulation_init()
|
||||
do while (openmc_next_batch() == 0)
|
||||
do
|
||||
err = openmc_next_batch(status)
|
||||
if (status /= 0 .or. err < 0) exit
|
||||
end do
|
||||
call openmc_simulation_finalize()
|
||||
|
||||
end subroutine openmc_run
|
||||
end function openmc_run
|
||||
|
||||
!===============================================================================
|
||||
! OPENMC_NEXT_BATCH
|
||||
!===============================================================================
|
||||
|
||||
function openmc_next_batch() result(retval) bind(C)
|
||||
integer(C_INT) :: retval
|
||||
function openmc_next_batch(status) result(err) bind(C)
|
||||
integer(C_INT), intent(out), optional :: status
|
||||
integer(C_INT) :: err
|
||||
|
||||
type(Particle) :: p
|
||||
integer(8) :: i_work
|
||||
|
||||
err = 0
|
||||
|
||||
! Make sure simulation has been initialized
|
||||
if (.not. simulation_initialized) then
|
||||
retval = -3
|
||||
err = E_ALLOCATE
|
||||
call set_errmsg("Simulation has not been initialized yet.")
|
||||
return
|
||||
end if
|
||||
|
||||
|
|
@ -86,7 +98,7 @@ contains
|
|||
! Handle restart runs
|
||||
if (restart_run .and. current_batch <= restart_batch) then
|
||||
call replay_batch_history()
|
||||
retval = 0
|
||||
status = STATUS_EXIT_NORMAL
|
||||
return
|
||||
end if
|
||||
|
||||
|
|
@ -124,12 +136,14 @@ contains
|
|||
call finalize_batch()
|
||||
|
||||
! Check simulation ending criteria
|
||||
if (current_batch == n_max_batches) then
|
||||
retval = -1
|
||||
elseif (satisfy_triggers) then
|
||||
retval = -2
|
||||
else
|
||||
retval = 0
|
||||
if (present(status)) then
|
||||
if (current_batch == n_max_batches) then
|
||||
status = STATUS_EXIT_MAX_BATCH
|
||||
elseif (satisfy_triggers) then
|
||||
status = STATUS_EXIT_ON_TRIGGER
|
||||
else
|
||||
status = STATUS_EXIT_NORMAL
|
||||
end if
|
||||
end if
|
||||
|
||||
end function openmc_next_batch
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ module tally_filter_mesh
|
|||
|
||||
implicit none
|
||||
private
|
||||
public :: openmc_mesh_filter_get_mesh
|
||||
public :: openmc_mesh_filter_set_mesh
|
||||
|
||||
!===============================================================================
|
||||
|
|
@ -280,35 +281,46 @@ contains
|
|||
! C API FUNCTIONS
|
||||
!===============================================================================
|
||||
|
||||
function openmc_mesh_filter_get_mesh(index, index_mesh) result(err) bind(C)
|
||||
! Get the mesh for a mesh filter
|
||||
integer(C_INT32_T), value, intent(in) :: index
|
||||
integer(C_INT32_T), intent(out) :: index_mesh
|
||||
integer(C_INT) :: err
|
||||
|
||||
err = verify_filter(index)
|
||||
if (err == 0) then
|
||||
select type (f => filters(index) % obj)
|
||||
type is (MeshFilter)
|
||||
index_mesh = f % mesh
|
||||
class default
|
||||
err = E_INVALID_TYPE
|
||||
call set_errmsg("Tried to set mesh on a non-mesh filter.")
|
||||
end select
|
||||
end if
|
||||
end function openmc_mesh_filter_get_mesh
|
||||
|
||||
|
||||
function openmc_mesh_filter_set_mesh(index, index_mesh) result(err) bind(C)
|
||||
! Set the mesh for a mesh filter
|
||||
integer(C_INT32_T), value, intent(in) :: index
|
||||
integer(C_INT32_T), value, intent(in) :: index_mesh
|
||||
integer(C_INT) :: err
|
||||
|
||||
err = 0
|
||||
if (index >= 1 .and. index <= n_filters) then
|
||||
if (allocated(filters(index) % obj)) then
|
||||
select type (f => filters(index) % obj)
|
||||
type is (MeshFilter)
|
||||
if (index_mesh >= 1 .and. index_mesh <= n_meshes) then
|
||||
f % mesh = index_mesh
|
||||
f % n_bins = product(meshes(index_mesh) % dimension)
|
||||
else
|
||||
err = E_OUT_OF_BOUNDS
|
||||
call set_errmsg("Index in 'meshes' array is out of bounds.")
|
||||
end if
|
||||
err = verify_filter(index)
|
||||
if (err == 0) then
|
||||
select type (f => filters(index) % obj)
|
||||
type is (MeshFilter)
|
||||
if (index_mesh >= 1 .and. index_mesh <= n_meshes) then
|
||||
f % mesh = index_mesh
|
||||
f % n_bins = product(meshes(index_mesh) % dimension)
|
||||
else
|
||||
err = E_OUT_OF_BOUNDS
|
||||
call set_errmsg("Index in 'meshes' array is out of bounds.")
|
||||
end if
|
||||
class default
|
||||
err = E_INVALID_TYPE
|
||||
call set_errmsg("Tried to set mesh on a non-mesh filter.")
|
||||
end select
|
||||
else
|
||||
err = E_ALLOCATE
|
||||
call set_errmsg("Filter type has not been set yet.")
|
||||
end if
|
||||
else
|
||||
err = E_OUT_OF_BOUNDS
|
||||
call set_errmsg("Index in filters array out of bounds.")
|
||||
err = E_INVALID_TYPE
|
||||
call set_errmsg("Tried to set mesh on a non-mesh filter.")
|
||||
end select
|
||||
end if
|
||||
end function openmc_mesh_filter_set_mesh
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ module tally_filter_meshsurface
|
|||
|
||||
implicit none
|
||||
private
|
||||
public :: openmc_meshsurface_filter_get_mesh
|
||||
public :: openmc_meshsurface_filter_set_mesh
|
||||
|
||||
!===============================================================================
|
||||
|
|
@ -296,6 +297,25 @@ contains
|
|||
! C API FUNCTIONS
|
||||
!===============================================================================
|
||||
|
||||
function openmc_meshsurface_filter_get_mesh(index, index_mesh) result(err) bind(C)
|
||||
! Get the mesh for a mesh surface filter
|
||||
integer(C_INT32_T), value, intent(in) :: index
|
||||
integer(C_INT32_T), intent(out) :: index_mesh
|
||||
integer(C_INT) :: err
|
||||
|
||||
err = verify_filter(index)
|
||||
if (err == 0) then
|
||||
select type (f => filters(index) % obj)
|
||||
type is (MeshSurfaceFilter)
|
||||
index_mesh = f % mesh
|
||||
class default
|
||||
err = E_INVALID_TYPE
|
||||
call set_errmsg("Tried to set mesh on a non-mesh filter.")
|
||||
end select
|
||||
end if
|
||||
end function openmc_meshsurface_filter_get_mesh
|
||||
|
||||
|
||||
function openmc_meshsurface_filter_set_mesh(index, index_mesh) result(err) bind(C)
|
||||
! Set the mesh for a mesh surface filter
|
||||
integer(C_INT32_T), value, intent(in) :: index
|
||||
|
|
@ -304,30 +324,22 @@ contains
|
|||
|
||||
integer :: n_dim
|
||||
|
||||
err = 0
|
||||
if (index >= 1 .and. index <= n_filters) then
|
||||
if (allocated(filters(index) % obj)) then
|
||||
select type (f => filters(index) % obj)
|
||||
type is (MeshSurfaceFilter)
|
||||
if (index_mesh >= 1 .and. index_mesh <= n_meshes) then
|
||||
f % mesh = index_mesh
|
||||
n_dim = meshes(index_mesh) % n_dimension
|
||||
f % n_bins = 4*n_dim*product(meshes(index_mesh) % dimension)
|
||||
else
|
||||
err = E_OUT_OF_BOUNDS
|
||||
call set_errmsg("Index in 'meshes' array is out of bounds.")
|
||||
end if
|
||||
class default
|
||||
err = E_INVALID_TYPE
|
||||
call set_errmsg("Tried to set mesh on a non-mesh filter.")
|
||||
end select
|
||||
else
|
||||
err = E_ALLOCATE
|
||||
call set_errmsg("Filter type has not been set yet.")
|
||||
end if
|
||||
else
|
||||
err = E_OUT_OF_BOUNDS
|
||||
call set_errmsg("Index in filters array out of bounds.")
|
||||
err = verify_filter(index)
|
||||
if (err == 0) then
|
||||
select type (f => filters(index) % obj)
|
||||
type is (MeshSurfaceFilter)
|
||||
if (index_mesh >= 1 .and. index_mesh <= n_meshes) then
|
||||
f % mesh = index_mesh
|
||||
n_dim = meshes(index_mesh) % n_dimension
|
||||
f % n_bins = 4*n_dim*product(meshes(index_mesh) % dimension)
|
||||
else
|
||||
err = E_OUT_OF_BOUNDS
|
||||
call set_errmsg("Index in 'meshes' array is out of bounds.")
|
||||
end if
|
||||
class default
|
||||
err = E_INVALID_TYPE
|
||||
call set_errmsg("Tried to set mesh on a non-mesh filter.")
|
||||
end select
|
||||
end if
|
||||
end function openmc_meshsurface_filter_set_mesh
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import os
|
|||
import numpy as np
|
||||
import pytest
|
||||
import openmc
|
||||
import openmc.exceptions as exc
|
||||
import openmc.capi
|
||||
|
||||
from tests import cdtemp
|
||||
|
|
@ -60,7 +61,7 @@ def test_cell(capi_init):
|
|||
|
||||
|
||||
def test_new_cell(capi_init):
|
||||
with pytest.raises(openmc.capi.AllocationError):
|
||||
with pytest.raises(exc.AllocationError):
|
||||
openmc.capi.Cell(1)
|
||||
new_cell = openmc.capi.Cell()
|
||||
new_cell_with_id = openmc.capi.Cell(10)
|
||||
|
|
@ -91,7 +92,7 @@ def test_material(capi_init):
|
|||
|
||||
|
||||
def test_new_material(capi_init):
|
||||
with pytest.raises(openmc.capi.AllocationError):
|
||||
with pytest.raises(exc.AllocationError):
|
||||
openmc.capi.Material(1)
|
||||
new_mat = openmc.capi.Material()
|
||||
new_mat_with_id = openmc.capi.Material(10)
|
||||
|
|
@ -109,7 +110,7 @@ def test_nuclide_mapping(capi_init):
|
|||
|
||||
def test_load_nuclide(capi_init):
|
||||
openmc.capi.load_nuclide('Pu239')
|
||||
with pytest.raises(openmc.capi.DataError):
|
||||
with pytest.raises(exc.DataError):
|
||||
openmc.capi.load_nuclide('Pu3')
|
||||
|
||||
|
||||
|
|
@ -145,7 +146,7 @@ def test_tally(capi_init):
|
|||
assert isinstance(t.filters[1], openmc.capi.EnergyFilter)
|
||||
|
||||
# Create new filter and replace existing
|
||||
with pytest.raises(openmc.capi.AllocationError):
|
||||
with pytest.raises(exc.AllocationError):
|
||||
openmc.capi.MaterialFilter(uid=1)
|
||||
mats = openmc.capi.materials
|
||||
f = openmc.capi.MaterialFilter([mats[2], mats[1]])
|
||||
|
|
@ -153,7 +154,7 @@ def test_tally(capi_init):
|
|||
assert t.filters == [f]
|
||||
|
||||
assert t.nuclides == ['U235', 'U238']
|
||||
with pytest.raises(openmc.capi.DataError):
|
||||
with pytest.raises(exc.DataError):
|
||||
t.nuclides = ['Zr2']
|
||||
t.nuclides = ['U234', 'Zr90']
|
||||
assert t.nuclides == ['U234', 'Zr90']
|
||||
|
|
@ -165,7 +166,7 @@ def test_tally(capi_init):
|
|||
|
||||
|
||||
def test_new_tally(capi_init):
|
||||
with pytest.raises(openmc.capi.AllocationError):
|
||||
with pytest.raises(exc.AllocationError):
|
||||
openmc.capi.Material(1)
|
||||
new_tally = openmc.capi.Tally()
|
||||
new_tally.scores = ['flux']
|
||||
|
|
@ -206,7 +207,7 @@ def test_by_batch(capi_run):
|
|||
|
||||
# Running next batch before simulation is initialized should raise an
|
||||
# exception
|
||||
with pytest.raises(openmc.capi.AllocationError):
|
||||
with pytest.raises(exc.AllocationError):
|
||||
openmc.capi.next_batch()
|
||||
|
||||
openmc.capi.simulation_init()
|
||||
|
|
@ -241,7 +242,7 @@ def test_find_cell(capi_init):
|
|||
assert cell is openmc.capi.cells[1]
|
||||
cell, instance = openmc.capi.find_cell((0.4, 0., 0.))
|
||||
assert cell is openmc.capi.cells[2]
|
||||
with pytest.raises(openmc.capi.GeometryError):
|
||||
with pytest.raises(exc.GeometryError):
|
||||
openmc.capi.find_cell((100., 100., 100.))
|
||||
|
||||
|
||||
|
|
@ -250,3 +251,38 @@ def test_find_material(capi_init):
|
|||
assert mat is openmc.capi.materials[1]
|
||||
mat = openmc.capi.find_material((0.4, 0., 0.))
|
||||
assert mat is openmc.capi.materials[2]
|
||||
|
||||
|
||||
def test_mesh(capi_init):
|
||||
mesh = openmc.capi.Mesh()
|
||||
mesh.dimension = (2, 3, 4)
|
||||
assert mesh.dimension == (2, 3, 4)
|
||||
with pytest.raises(exc.AllocationError):
|
||||
mesh2 = openmc.capi.Mesh(mesh.id)
|
||||
|
||||
# Make sure each combination of parameters works
|
||||
ll = (0., 0., 0.)
|
||||
ur = (10., 10., 10.)
|
||||
width = (1., 1., 1.)
|
||||
mesh.set_parameters(lower_left=ll, upper_right=ur)
|
||||
assert mesh.lower_left == pytest.approx(ll)
|
||||
assert mesh.upper_right == pytest.approx(ur)
|
||||
mesh.set_parameters(lower_left=ll, width=width)
|
||||
assert mesh.lower_left == pytest.approx(ll)
|
||||
assert mesh.width == pytest.approx(width)
|
||||
mesh.set_parameters(upper_right=ur, width=width)
|
||||
assert mesh.upper_right == pytest.approx(ur)
|
||||
assert mesh.width == pytest.approx(width)
|
||||
|
||||
meshes = openmc.capi.meshes
|
||||
assert isinstance(meshes, Mapping)
|
||||
assert len(meshes) == 1
|
||||
for mesh_id, mesh in meshes.items():
|
||||
assert isinstance(mesh, openmc.capi.Mesh)
|
||||
assert mesh_id == mesh.id
|
||||
|
||||
mf = openmc.capi.MeshFilter(mesh)
|
||||
assert mf.mesh == mesh
|
||||
|
||||
msf = openmc.capi.MeshSurfaceFilter(mesh)
|
||||
assert msf.mesh == mesh
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue