Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c547b57
Add filter_get_bins interface (not efficient for plotter)
paulromano Apr 24, 2025
7f668bc
Combine filter index search with id_map
paulromano Jul 25, 2025
2287926
Implement new openmc_raster_plot function
paulromano Jan 31, 2026
b12b92e
Avoid duplicated code in get_raster_map
paulromano Jan 31, 2026
e86c060
Remove get_plot_bins for Filter
paulromano Jan 31, 2026
2e81cb0
Add tests for raster_plot
paulromano Jan 31, 2026
d80198b
Small doc fix
paulromano Feb 2, 2026
3db1e54
Initial shot at arbitrary orientation slice plots
paulromano Feb 3, 2026
adf7ad3
Remove 'axes' and reorder arguments in lib.raster_plot
paulromano Feb 4, 2026
fceb98c
Support u_span and v_span in Model.raster_plot
paulromano Feb 4, 2026
ac0e900
Rename raster -> slice for consistency
paulromano Feb 8, 2026
4d6c610
Merge branch 'develop' into slice-plot-api
paulromano Feb 14, 2026
6533034
Restore original (arbitrary) direction for slice plotting
paulromano Feb 16, 2026
4824efa
Revert changes to comments
paulromano Feb 16, 2026
1485504
Merge branch 'develop' into slice-plot-api
paulromano Mar 3, 2026
447efcc
Merge branch 'develop' into slice-plot-api
paulromano May 18, 2026
6a3904b
Deprecation of id_map/property_map/_PlotBase
paulromano Feb 9, 2026
8f3a063
Use Model.slice_plot within Model.id_map
paulromano Jun 3, 2026
47dc02c
Use slice_plot in plot rather than id_map
paulromano Jun 3, 2026
60773c2
Simplify deprecated interface for lib.id_map/property_map
paulromano Jun 3, 2026
705330a
Only compute filter ID set when needed
paulromano Jun 3, 2026
93fff74
missing blank line
paulromano Jun 3, 2026
6513ef8
Use Direction instead of Position for spans
paulromano Jun 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions include/openmc/capi.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,13 @@ int openmc_new_filter(const char* type, int32_t* index);
int openmc_next_batch(int* status);
int openmc_nuclide_name(int index, const char** name);
int openmc_plot_geometry();
// Deprecated; use openmc_slice_plot.
int openmc_id_map(const void* slice, int32_t* data_out);
// Deprecated; use openmc_slice_plot.
int openmc_property_map(const void* slice, double* data_out);
int openmc_slice_plot(const double origin[3], const double u_span[3],
const double v_span[3], const size_t pixels[2], bool color_overlaps,
int level, int32_t filter_index, int32_t* geom_data, double* property_data);
int openmc_get_plot_index(int32_t id, int32_t* index);
int openmc_plot_get_id(int32_t index, int32_t* id);
int openmc_plot_set_id(int32_t index, int32_t id);
Expand Down
102 changes: 60 additions & 42 deletions include/openmc/plot.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include "openmc/position.h"
#include "openmc/random_lcg.h"
#include "openmc/ray.h"
#include "openmc/tallies/filter.h"
#include "openmc/tallies/filter_match.h"
#include "openmc/xml_interface.h"

namespace openmc {
Expand Down Expand Up @@ -148,10 +150,11 @@ class PlottableInterface {

struct IdData {
// Constructor
IdData(size_t h_res, size_t v_res);
IdData(size_t h_res, size_t v_res, bool include_filter = false);

// Methods
void set_value(size_t y, size_t x, const GeometryState& p, int level);
void set_value(size_t y, size_t x, const Particle& p, int level,
Filter* filter = nullptr, FilterMatch* match = nullptr);
void set_overlap(size_t y, size_t x);

// Members
Expand All @@ -160,24 +163,42 @@ struct IdData {

struct PropertyData {
// Constructor
PropertyData(size_t h_res, size_t v_res);
PropertyData(size_t h_res, size_t v_res, bool include_filter = false);

// Methods
void set_value(size_t y, size_t x, const GeometryState& p, int level);
void set_value(size_t y, size_t x, const Particle& p, int level,
Filter* filter = nullptr, FilterMatch* match = nullptr);
void set_overlap(size_t y, size_t x);

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

struct RasterData {
// Constructor
RasterData(size_t h_res, size_t v_res, bool include_filter = false);

// Methods
void set_value(size_t y, size_t x, const Particle& p, int level,
Filter* filter = nullptr, FilterMatch* match = nullptr);
void set_overlap(size_t y, size_t x);

// Members
tensor::Tensor<int32_t>
id_data_; //!< [v_res, h_res, 3 or 4]: cell, instance, mat, [filter_bin]
tensor::Tensor<double>
property_data_; //!< [v_res, h_res, 2]: temperature, density
bool include_filter_; //!< Whether filter bin index is included
};

//===============================================================================
// Plot class
//===============================================================================

class SlicePlotBase {
public:
template<class T>
T get_map() const;
T get_map(int32_t filter_index = -1) const;

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

Expand All @@ -189,69 +210,64 @@ class SlicePlotBase {
// Members
public:
Position origin_; //!< Plot origin in geometry
Position width_; //!< Plot width in geometry
PlotBasis basis_; //!< Plot basis (XY/XZ/YZ)
Direction u_span_; //!< Full-width span vector in geometry
Direction v_span_; //!< Full-height span vector in geometry
array<size_t, 3> pixels_; //!< Plot size in pixels
bool slice_color_overlaps_; //!< Show overlapping cells?
int slice_level_ {-1}; //!< Plot universe level
private:
};

template<class T>
T SlicePlotBase::get_map() const
T SlicePlotBase::get_map(int32_t filter_index) const
{

size_t width = pixels_[0];
size_t height = pixels_[1];

// get pixel size
double in_pixel = (width_[0]) / static_cast<double>(width);
double out_pixel = (width_[1]) / static_cast<double>(height);
// Determine if filter is being used
bool include_filter = (filter_index >= 0);
Filter* filter = nullptr;
if (include_filter) {
filter = model::tally_filters[filter_index].get();
}

// size data array
T data(width, height);

// setup basis indices and initial position centered on pixel
int in_i, out_i;
Position xyz = origin_;
switch (basis_) {
case PlotBasis::xy:
in_i = 0;
out_i = 1;
break;
case PlotBasis::xz:
in_i = 0;
out_i = 2;
break;
case PlotBasis::yz:
in_i = 1;
out_i = 2;
break;
default:
UNREACHABLE();
}
T data(width, height, include_filter);

// set initial position
xyz[in_i] = origin_[in_i] - width_[0] / 2. + in_pixel / 2.;
xyz[out_i] = origin_[out_i] + width_[1] / 2. - out_pixel / 2.;
// compute pixel steps and top-left pixel center
Direction u_step = u_span_ / static_cast<double>(width);
Direction v_step = v_span_ / static_cast<double>(height);

Position start =
origin_ - 0.5 * u_span_ + 0.5 * v_span_ + 0.5 * u_step - 0.5 * v_step;

// Validate that span vectors define a valid plane
Position cross = u_span_.cross(v_span_);
if (cross.norm() == 0.0) {
fatal_error("Slice span vectors are invalid (zero area).");
}

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

#pragma omp parallel
{
GeometryState p;
p.r() = xyz;
Particle p;
p.r() = start;
p.u() = dir;
p.coord(0).universe() = model::root_universe;
int level = slice_level_;
int j {};
FilterMatch match;

#pragma omp for
for (int y = 0; y < height; y++) {
p.r()[out_i] = xyz[out_i] - out_pixel * y;
Position row = start - v_step * static_cast<double>(y);
for (int x = 0; x < width; x++) {
p.r()[in_i] = xyz[in_i] + in_pixel * x;
p.r() = row + u_step * static_cast<double>(x);
p.n_coord() = 1;
// local variables
bool found_cell = exhaustive_find_cell(p);
Expand All @@ -260,7 +276,7 @@ T SlicePlotBase::get_map() const
j = level;
}
if (found_cell) {
data.set_value(y, x, p, j);
data.set_value(y, x, p, j, filter, &match);
}
if (slice_color_overlaps_ && check_cell_overlap(p, false)) {
data.set_overlap(y, x);
Expand Down Expand Up @@ -297,6 +313,8 @@ class Plot : public PlottableInterface, public SlicePlotBase {
void print_info() const override;

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