mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-28 22:26:08 -04:00
Correction to n_coord reset on particle for proper handling of universes.
Renaming CPlot to PlotBase and adding a capi test. Mirroring use of Bank in the capi. Updating header name. Adding documentation to capi plot module. Removing plot base header and struct.
This commit is contained in:
parent
b0bafee385
commit
a371f402a2
5 changed files with 125 additions and 53 deletions
|
|
@ -70,6 +70,7 @@ extern "C" {
|
|||
int openmc_next_batch(int* status);
|
||||
int openmc_nuclide_name(int index, const char** name);
|
||||
int openmc_plot_geometry();
|
||||
int openmc_id_map(void* slice, int32_t *data_out);
|
||||
int openmc_reset();
|
||||
int openmc_run();
|
||||
void openmc_set_seed(int64_t new_seed);
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ namespace openmc {
|
|||
//===============================================================================
|
||||
|
||||
class Plot;
|
||||
class PlotC;
|
||||
|
||||
|
||||
namespace model {
|
||||
|
||||
|
|
@ -74,21 +74,16 @@ enum class PlotColorBy {
|
|||
//===============================================================================
|
||||
// Plot class
|
||||
//===============================================================================
|
||||
|
||||
|
||||
// plot class for interaction with external code
|
||||
class CPlot {
|
||||
|
||||
public:
|
||||
struct Slice {
|
||||
// Members
|
||||
Position origin_; //!< Plot origin in geometry
|
||||
Position width_; //!< Plot width in geometry
|
||||
PlotBasis basis_; //!< Plot basis (XY/XZ/YZ)
|
||||
std::array<int, 3> pixels_; //!< Plot size in pixels
|
||||
int pixels_[3]; //!< Plot size in pixels
|
||||
int level_; //!< Plot universe level
|
||||
};
|
||||
|
||||
|
||||
class Plot : public CPlot
|
||||
class Plot : public Slice
|
||||
{
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -6,19 +6,18 @@ from .error import _error_handler
|
|||
|
||||
import numpy as np
|
||||
|
||||
class _IntThree():
|
||||
type_ = c_int*3
|
||||
val_ = None
|
||||
def __init__(self, vals=None):
|
||||
if vals and iterable(vals) and all(vals == int):
|
||||
self.val_ = type_(vals[0], vals[1], vals[2])
|
||||
else:
|
||||
raise ValueError("{} is not a valid object to construct IntThree.".format(vals))
|
||||
|
||||
def __str__(self):
|
||||
return "({}, {}, {})".format(self.val_[0], self.val_[1], self.val_[2])
|
||||
|
||||
class _Position(Structure):
|
||||
"""Definition of an xyz location in space with underlying c-types
|
||||
|
||||
C-type Attributes
|
||||
-----------------
|
||||
x : c_double
|
||||
Position's x value (default: 0.0)
|
||||
y : c_double
|
||||
Position's y value (default: 0.0)
|
||||
z : c_double
|
||||
Position's z value (default: 0.0)
|
||||
"""
|
||||
_fields_ = [('x', c_double),
|
||||
('y', c_double),
|
||||
('z', c_double)]
|
||||
|
|
@ -61,9 +60,43 @@ class _Position(Structure):
|
|||
self.z = z_val
|
||||
|
||||
def __str__(self):
|
||||
return "({}, {}, {})".format(self.x, self.y, self.z)
|
||||
return "Position: ({}, {}, {})".format(self.x, self.y, self.z)
|
||||
|
||||
|
||||
class _Plot(Structure):
|
||||
"""A Plot structure defining a 2-D slice with underlying c-types
|
||||
|
||||
C-Type Attributes
|
||||
-----------------
|
||||
origin : openmc.capi.plot._Position
|
||||
A position defining the origin of the plot.
|
||||
width_ : openmc.capi.plot._Position
|
||||
The width of the plot along the x, y, and z axes, respectively
|
||||
basis_ : c_int
|
||||
The axes basis of the plot view.
|
||||
pixels_ : c_int[3]
|
||||
The resolution of the plot in the horizontal and vertical dimensions
|
||||
level_ : c_int
|
||||
The universe level for the plot view
|
||||
|
||||
Attributes
|
||||
----------
|
||||
origin : tuple or list of ndarray
|
||||
Origin (center) of the plot
|
||||
width : float
|
||||
The horizontal dimension of the plot in geometry units (cm)
|
||||
height : float
|
||||
The vertical dimension of the plot in geometry units (cm)
|
||||
basis : string
|
||||
One of {'xy', 'xz', 'yz'} indicating the horizontal and vertical
|
||||
axes of the plot.
|
||||
hRes : float
|
||||
The horizontal resolution of the plot in pixels
|
||||
vRes : float
|
||||
The vertical resolution of the plot in pixels
|
||||
level : int
|
||||
The universe level for the plot (default: -1 -> all universes shown)
|
||||
"""
|
||||
_fields_ = [('origin_', _Position),
|
||||
('width_', _Position),
|
||||
('basis_', c_int),
|
||||
|
|
@ -127,6 +160,7 @@ class _Plot(Structure):
|
|||
def basis(self, basis):
|
||||
if isinstance(basis, str):
|
||||
valid_bases = ('xy', 'xz', 'yz')
|
||||
basis = basis.lower()
|
||||
if basis not in valid_bases:
|
||||
raise ValueError("{} is not a valid plot basis.".format(basis))
|
||||
|
||||
|
|
@ -159,25 +193,43 @@ class _Plot(Structure):
|
|||
def level(self, level):
|
||||
self.level_ = level
|
||||
|
||||
def __str__(self):
|
||||
out_str = "-------"
|
||||
def __repr__(self):
|
||||
out_str = "-----\n"
|
||||
out_str += "Plot:\n"
|
||||
out_str += "-------"
|
||||
out_str += "Origin: " + str(self.origin) + "\n"
|
||||
out_str += "Width: " + str(self.width) + "\n"
|
||||
out_str += "Height: " + str(self.height) + "\n"
|
||||
out_str += "Basis: " + str(self.basis) + "\n"
|
||||
out_str += "HRes: " + str(self.hRes) + "\n"
|
||||
out_str += "VRes: " + str(self.vRes) + "\n"
|
||||
out_str += "Level: " + str(self.level) + "\n"
|
||||
out_str += "-----\n"
|
||||
out_str += "Origin: {}\n".format(self.origin)
|
||||
out_str += "Width: {}\n".format(self.width)
|
||||
out_str += "Height: {}\n".format(self.height)
|
||||
out_str += "Basis: {}\n".format(self.basis)
|
||||
out_str += "HRes: {}\n".format(self.hRes)
|
||||
out_str += "VRes: {}\n".format(self.vRes)
|
||||
out_str += "Level: {}\n".format(self.level)
|
||||
return out_str
|
||||
|
||||
def __str__(self):
|
||||
return self.__repr__()
|
||||
|
||||
|
||||
_dll.openmc_id_map.argtypes= [POINTER(_Plot),]
|
||||
_dll.openmc_id_map.restype = c_int
|
||||
_dll.openmc_id_map.errcheck = _error_handler
|
||||
|
||||
|
||||
def id_map(plot):
|
||||
img_data = np.zeros((plot.pixels_[1], plot.pixels_[0], 2), dtype=np.dtype('int32'))
|
||||
out = _dll.openmc_id_map(POINTER(_Plot)(plot), img_data.ctypes.data_as(POINTER(c_int32)))
|
||||
"""
|
||||
Generate a 2-D map of (cell_id, material_id). Used for in-memory image generation.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
plot : An openmc.capi.plot._Plot object describing the slice of the model to
|
||||
be generated
|
||||
|
||||
Returns
|
||||
-------
|
||||
id_map : a NumPy array with shape (vertical pixels, horizontal pixels, 2)
|
||||
of OpenMC property ids with dtype int32
|
||||
|
||||
"""
|
||||
img_data = np.zeros((plot.vRes, plot.hRes, 2), dtype=np.dtype('int32'))
|
||||
_dll.openmc_id_map(POINTER(_Plot)(plot), img_data.ctypes.data_as(POINTER(c_int32)))
|
||||
return img_data
|
||||
|
|
|
|||
39
src/plot.cpp
39
src/plot.cpp
|
|
@ -886,7 +886,8 @@ void create_voxel(Plot pl)
|
|||
// Write current date and time
|
||||
write_attribute(file_id, "date_and_time", time_stamp().c_str());
|
||||
hsize_t three = 3;
|
||||
write_attribute(file_id, "num_voxels", pl.pixels_);
|
||||
std::array<int, 3> pixels = {pl.pixels_[0], pl.pixels_[1], pl.pixels_[2]};
|
||||
write_attribute(file_id, "num_voxels", pixels);
|
||||
write_attribute(file_id, "voxel_width", vox);
|
||||
write_attribute(file_id, "lower_left", ll);
|
||||
|
||||
|
|
@ -979,40 +980,42 @@ RGBColor random_color() {
|
|||
return {int(prn()*255), int(prn()*255), int(prn()*255)};
|
||||
}
|
||||
|
||||
extern "C" int openmc_id_map(const CPlot& pl, int* data_out) {
|
||||
extern "C" int openmc_id_map(void* slice, int32_t* data_out) {
|
||||
|
||||
size_t width = pl.pixels_[0];
|
||||
size_t height = pl.pixels_[1];
|
||||
auto* sl = static_cast<Slice*>(slice);
|
||||
|
||||
double in_pixel = (pl.width_[0])/static_cast<double>(width);
|
||||
double out_pixel = (pl.width_[1])/static_cast<double>(height);
|
||||
size_t width = sl->pixels_[0];
|
||||
size_t height = sl->pixels_[1];
|
||||
|
||||
double in_pixel = (sl->width_[0])/static_cast<double>(width);
|
||||
double out_pixel = (sl->width_[1])/static_cast<double>(height);
|
||||
|
||||
IDData data;
|
||||
data.resize({height, width, 2});
|
||||
|
||||
int in_i, out_i;
|
||||
double xyz[3];
|
||||
switch(pl.basis_) {
|
||||
switch(sl->basis_) {
|
||||
case PlotBasis::xy :
|
||||
in_i = 0;
|
||||
out_i = 1;
|
||||
xyz[0] = pl.origin_[0] - pl.width_[0] / 2.;
|
||||
xyz[1] = pl.origin_[1] + pl.width_[1] / 2.;
|
||||
xyz[2] = pl.origin_[2];
|
||||
xyz[0] = sl->origin_[0] - sl->width_[0] / 2. + in_pixel / 2.;
|
||||
xyz[1] = sl->origin_[1] + sl->width_[1] / 2. - out_pixel / 2.;
|
||||
xyz[2] = sl->origin_[2];
|
||||
break;
|
||||
case PlotBasis::xz :
|
||||
in_i = 0;
|
||||
out_i = 2;
|
||||
xyz[0] = pl.origin_[0] - pl.width_[0] / 2.;
|
||||
xyz[1] = pl.origin_[1];
|
||||
xyz[2] = pl.origin_[2] + pl.width_[1] / 2.;
|
||||
xyz[0] = sl->origin_[0] - sl->width_[0] / 2. + in_pixel / 2.;
|
||||
xyz[1] = sl->origin_[1];
|
||||
xyz[2] = sl->origin_[2] + sl->width_[1] / 2. - out_pixel / 2.;
|
||||
break;
|
||||
case PlotBasis::yz :
|
||||
in_i = 1;
|
||||
out_i = 2;
|
||||
xyz[0] = pl.origin_[0];
|
||||
xyz[1] = pl.origin_[1] - pl.width_[0] / 2.;
|
||||
xyz[2] = pl.origin_[2] + pl.width_[1] / 2.;
|
||||
xyz[0] = sl->origin_[0];
|
||||
xyz[1] = sl->origin_[1] - sl->width_[0] / 2. + in_pixel / 2.;
|
||||
xyz[2] = sl->origin_[2] + sl->width_[1] / 2. - out_pixel / 2.;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -1025,15 +1028,15 @@ extern "C" int openmc_id_map(const CPlot& pl, int* data_out) {
|
|||
std::copy(xyz, xyz+3, p.coord[0].xyz);
|
||||
std::copy(dir, dir+3, p.coord[0].uvw);
|
||||
p.coord[0].universe = model::root_universe;
|
||||
int level = pl.level_;
|
||||
int level = sl->level_;
|
||||
int j{};
|
||||
|
||||
#pragma omp for
|
||||
for (int y = 0; y < height; y++) {
|
||||
p.coord[0].xyz[out_i] = xyz[out_i] - out_pixel * y;
|
||||
p.n_coord = 1;
|
||||
for (int x = 0; x < width; x++) {
|
||||
p.coord[0].xyz[in_i] = xyz[in_i] + in_pixel * x;
|
||||
p.n_coord = 1;
|
||||
// local variables
|
||||
bool found_cell = find_cell(&p, 0);
|
||||
j = p.n_coord - 1;
|
||||
|
|
|
|||
|
|
@ -400,3 +400,24 @@ def test_load_nuclide(capi_init):
|
|||
# load non-existent nuclide
|
||||
with pytest.raises(exc.DataError):
|
||||
openmc.capi.load_nuclide('Pu3')
|
||||
|
||||
|
||||
def test_id_map(capi_init):
|
||||
expected_ids = np.array([[(3,3), (2,2), (3,3)],
|
||||
[(2,2), (1,1), (2,2)],
|
||||
[(3,3), (2,2), (3,3)]], dtype = 'int32')
|
||||
|
||||
# create a plot object
|
||||
p = openmc.capi.plot._Plot()
|
||||
|
||||
p.width = 1.26
|
||||
p.height = 1.26
|
||||
p.vRes = 3
|
||||
p.hRes = 3
|
||||
p.origin = (0,0,0)
|
||||
p.basis = 'xy'
|
||||
p.level = -1
|
||||
|
||||
ids = openmc.capi.plot.id_map(p)
|
||||
print(ids)
|
||||
assert np.array_equal(expected_ids, ids)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue