Skip to content

Commit 4f6a25e

Browse files
authored
Introduce new C API function for slice plots (#3806)
1 parent db322f2 commit 4f6a25e

7 files changed

Lines changed: 763 additions & 291 deletions

File tree

include/openmc/capi.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,13 @@ int openmc_new_filter(const char* type, int32_t* index);
123123
int openmc_next_batch(int* status);
124124
int openmc_nuclide_name(int index, const char** name);
125125
int openmc_plot_geometry();
126+
// Deprecated; use openmc_slice_data.
126127
int openmc_id_map(const void* slice, int32_t* data_out);
128+
// Deprecated; use openmc_slice_data.
127129
int openmc_property_map(const void* slice, double* data_out);
130+
int openmc_slice_data(const double origin[3], const double u_span[3],
131+
const double v_span[3], const size_t pixels[2], bool show_overlaps, int level,
132+
int32_t filter_index, int32_t* geom_data, double* property_data);
128133
int openmc_get_plot_index(int32_t id, int32_t* index);
129134
int openmc_plot_get_id(int32_t index, int32_t* id);
130135
int openmc_plot_set_id(int32_t index, int32_t id);

include/openmc/plot.h

Lines changed: 65 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include "openmc/position.h"
1919
#include "openmc/random_lcg.h"
2020
#include "openmc/ray.h"
21+
#include "openmc/tallies/filter.h"
22+
#include "openmc/tallies/filter_match.h"
2123
#include "openmc/xml_interface.h"
2224

2325
namespace openmc {
@@ -148,10 +150,11 @@ class PlottableInterface {
148150

149151
struct IdData {
150152
// Constructor
151-
IdData(size_t h_res, size_t v_res);
153+
IdData(size_t h_res, size_t v_res, bool include_filter = false);
152154

153155
// Methods
154-
void set_value(size_t y, size_t x, const GeometryState& p, int level);
156+
void set_value(size_t y, size_t x, const Particle& p, int level,
157+
Filter* filter = nullptr, FilterMatch* match = nullptr);
155158
void set_overlap(size_t y, size_t x);
156159

157160
// Members
@@ -160,24 +163,42 @@ struct IdData {
160163

161164
struct PropertyData {
162165
// Constructor
163-
PropertyData(size_t h_res, size_t v_res);
166+
PropertyData(size_t h_res, size_t v_res, bool include_filter = false);
164167

165168
// Methods
166-
void set_value(size_t y, size_t x, const GeometryState& p, int level);
169+
void set_value(size_t y, size_t x, const Particle& p, int level,
170+
Filter* filter = nullptr, FilterMatch* match = nullptr);
167171
void set_overlap(size_t y, size_t x);
168172

169173
// Members
170174
tensor::Tensor<double> data_; //!< 2D array of temperature & density data
171175
};
172176

177+
struct RasterData {
178+
// Constructor
179+
RasterData(size_t h_res, size_t v_res, bool include_filter = false);
180+
181+
// Methods
182+
void set_value(size_t y, size_t x, const Particle& p, int level,
183+
Filter* filter = nullptr, FilterMatch* match = nullptr);
184+
void set_overlap(size_t y, size_t x);
185+
186+
// Members
187+
tensor::Tensor<int32_t>
188+
id_data_; //!< [v_res, h_res, 3 or 4]: cell, instance, mat, [filter_bin]
189+
tensor::Tensor<double>
190+
property_data_; //!< [v_res, h_res, 2]: temperature, density
191+
bool include_filter_; //!< Whether filter bin index is included
192+
};
193+
173194
//===============================================================================
174195
// Plot class
175196
//===============================================================================
176197

177198
class SlicePlotBase {
178199
public:
179200
template<class T>
180-
T get_map() const;
201+
T get_map(int32_t filter_index = -1) const;
181202

182203
enum class PlotBasis { xy = 1, xz = 2, yz = 3 };
183204

@@ -188,70 +209,65 @@ class SlicePlotBase {
188209

189210
// Members
190211
public:
191-
Position origin_; //!< Plot origin in geometry
192-
Position width_; //!< Plot width in geometry
193-
PlotBasis basis_; //!< Plot basis (XY/XZ/YZ)
194-
array<size_t, 3> pixels_; //!< Plot size in pixels
195-
bool slice_color_overlaps_; //!< Show overlapping cells?
196-
int slice_level_ {-1}; //!< Plot universe level
212+
Position origin_; //!< Plot origin in geometry
213+
Direction u_span_; //!< Full-width span vector in geometry
214+
Direction v_span_; //!< Full-height span vector in geometry
215+
array<size_t, 3> pixels_; //!< Plot size in pixels
216+
bool show_overlaps_; //!< Show overlapping cells?
217+
int slice_level_ {-1}; //!< Plot universe level
197218
private:
198219
};
199220

200221
template<class T>
201-
T SlicePlotBase::get_map() const
222+
T SlicePlotBase::get_map(int32_t filter_index) const
202223
{
203224

204225
size_t width = pixels_[0];
205226
size_t height = pixels_[1];
206227

207-
// get pixel size
208-
double in_pixel = (width_[0]) / static_cast<double>(width);
209-
double out_pixel = (width_[1]) / static_cast<double>(height);
228+
// Determine if filter is being used
229+
bool include_filter = (filter_index >= 0);
230+
Filter* filter = nullptr;
231+
if (include_filter) {
232+
filter = model::tally_filters[filter_index].get();
233+
}
210234

211235
// size data array
212-
T data(width, height);
213-
214-
// setup basis indices and initial position centered on pixel
215-
int in_i, out_i;
216-
Position xyz = origin_;
217-
switch (basis_) {
218-
case PlotBasis::xy:
219-
in_i = 0;
220-
out_i = 1;
221-
break;
222-
case PlotBasis::xz:
223-
in_i = 0;
224-
out_i = 2;
225-
break;
226-
case PlotBasis::yz:
227-
in_i = 1;
228-
out_i = 2;
229-
break;
230-
default:
231-
UNREACHABLE();
232-
}
236+
T data(width, height, include_filter);
233237

234-
// set initial position
235-
xyz[in_i] = origin_[in_i] - width_[0] / 2. + in_pixel / 2.;
236-
xyz[out_i] = origin_[out_i] + width_[1] / 2. - out_pixel / 2.;
238+
// compute pixel steps and top-left pixel center
239+
Direction u_step = u_span_ / static_cast<double>(width);
240+
Direction v_step = v_span_ / static_cast<double>(height);
241+
242+
Position start =
243+
origin_ - 0.5 * u_span_ + 0.5 * v_span_ + 0.5 * u_step - 0.5 * v_step;
244+
245+
// Validate that span vectors define a valid plane
246+
Position cross = u_span_.cross(v_span_);
247+
if (cross.norm() == 0.0) {
248+
fatal_error("Slice span vectors are invalid (zero area).");
249+
}
237250

238-
// arbitrary direction
239-
Direction dir = {1. / std::sqrt(2.), 1. / std::sqrt(2.), 0.0};
251+
// Use an arbitrary direction that is not aligned with any coordinate axis.
252+
// The direction has no physical meaning for plotting but is used by
253+
// Surface::sense() to break ties when a pixel is coincident with a surface.
254+
Direction dir = {1.0 / std::sqrt(2.0), 1.0 / std::sqrt(2.0), 0.0};
240255

241256
#pragma omp parallel
242257
{
243-
GeometryState p;
244-
p.r() = xyz;
258+
Particle p;
259+
p.r() = start;
245260
p.u() = dir;
246261
p.coord(0).universe() = model::root_universe;
247262
int level = slice_level_;
248263
int j {};
264+
FilterMatch match;
249265

250266
#pragma omp for
251267
for (int y = 0; y < height; y++) {
252-
p.r()[out_i] = xyz[out_i] - out_pixel * y;
268+
Position row = start - v_step * static_cast<double>(y);
253269
for (int x = 0; x < width; x++) {
254-
p.r()[in_i] = xyz[in_i] + in_pixel * x;
270+
p.r() = row + u_step * static_cast<double>(x);
255271
p.n_coord() = 1;
256272
// local variables
257273
bool found_cell = exhaustive_find_cell(p);
@@ -260,9 +276,9 @@ T SlicePlotBase::get_map() const
260276
j = level;
261277
}
262278
if (found_cell) {
263-
data.set_value(y, x, p, j);
279+
data.set_value(y, x, p, j, filter, &match);
264280
}
265-
if (slice_color_overlaps_ && check_cell_overlap(p, false)) {
281+
if (show_overlaps_ && check_cell_overlap(p, false)) {
266282
data.set_overlap(y, x);
267283
}
268284
} // inner for
@@ -297,6 +313,8 @@ class Plot : public PlottableInterface, public SlicePlotBase {
297313
void print_info() const override;
298314

299315
PlotType type_; //!< Plot type (Slice/Voxel)
316+
Position width_; //!< Axis-aligned width from plot.xml
317+
PlotBasis basis_; //!< Basis from plot.xml for slice plots
300318
int meshlines_width_; //!< Width of lines added to the plot
301319
int index_meshlines_mesh_ {-1}; //!< Index of the mesh to draw on the plot
302320
RGBColor meshlines_color_; //!< Color of meshlines on the plot

0 commit comments

Comments
 (0)