• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

openmc-dev / openmc / 5939695269

22 Aug 2023 01:45PM UTC coverage: 84.437% (-0.1%) from 84.572%
5939695269

push

github

web-flow
Expose universe plotting for the geometry class  (#2661)

1 of 2 new or added lines in 1 file covered. (50.0%)

67 existing lines in 11 files now uncovered.

46794 of 55419 relevant lines covered (84.44%)

82403428.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/include/openmc/plot.h
1
#ifndef OPENMC_PLOT_H
2
#define OPENMC_PLOT_H
3

4
#include <sstream>
5
#include <unordered_map>
6

7
#include "pugixml.hpp"
8
#include "xtensor/xarray.hpp"
9

10
#include "hdf5.h"
11
#include "openmc/cell.h"
12
#include "openmc/constants.h"
13
#include "openmc/error.h"
14
#include "openmc/geometry.h"
15
#include "openmc/particle.h"
16
#include "openmc/position.h"
17
#include "openmc/random_lcg.h"
18
#include "openmc/xml_interface.h"
19

20
namespace openmc {
21

22
//===============================================================================
23
// Global variables
24
//===============================================================================
25

26
class PlottableInterface;
27

28
namespace model {
29

30
extern std::unordered_map<int, int> plot_map; //!< map of plot ids to index
31
extern vector<std::unique_ptr<PlottableInterface>>
32
  plots; //!< Plot instance container
33

34
extern uint64_t plotter_seed; // Stream index used by the plotter
35

36
} // namespace model
37

38
//===============================================================================
39
// RGBColor holds color information for plotted objects
40
//===============================================================================
41

42
struct RGBColor {
43
  // Constructors
44
  RGBColor() : red(0), green(0), blue(0) {};
45
  RGBColor(const int v[3]) : red(v[0]), green(v[1]), blue(v[2]) {};
UNCOV
46
  RGBColor(int r, int g, int b) : red(r), green(g), blue(b) {};
×
47

48
  RGBColor(const vector<int>& v)
49
  {
50
    if (v.size() != 3) {
51
      throw std::out_of_range("Incorrect vector size for RGBColor.");
52
    }
53
    red = v[0];
54
    green = v[1];
55
    blue = v[2];
56
  }
57

58
  bool operator==(const RGBColor& other)
59
  {
60
    return red == other.red && green == other.green && blue == other.blue;
61
  }
62

63
  // Members
64
  uint8_t red, green, blue;
65
};
66

67
// some default colors
68
const RGBColor WHITE {255, 255, 255};
69
const RGBColor RED {255, 0, 0};
70
const RGBColor BLACK {0, 0, 0};
71

72
/*
73
 * PlottableInterface classes just have to have a unique ID in the plots.xml
74
 * file, and guarantee being able to create output in some way.
75
 */
76
class PlottableInterface {
77
private:
78
  void set_id(pugi::xml_node plot_node);
79
  int id_; // unique plot ID
80

81
  void set_bg_color(pugi::xml_node plot_node);
82
  void set_universe(pugi::xml_node plot_node);
83
  void set_default_colors(pugi::xml_node plot_node);
84
  void set_user_colors(pugi::xml_node plot_node);
85
  void set_overlap_color(pugi::xml_node plot_node);
86
  void set_mask(pugi::xml_node plot_node);
87

88
protected:
89
  // Plot output filename, derived classes have logic to set it
90
  std::string path_plot_;
91

92
public:
93
  enum class PlotColorBy { cells = 0, mats = 1 };
94

95
  // Creates the output image named path_plot_
96
  virtual void create_output() const = 0;
97

98
  // Print useful info to the terminal
99
  virtual void print_info() const = 0;
100

101
  const std::string& path_plot() const { return path_plot_; }
102
  const int id() const { return id_; }
103
  const int level() const { return level_; }
104

105
  // Public color-related data
106
  PlottableInterface(pugi::xml_node plot_node);
107
  virtual ~PlottableInterface() = default;
108
  int level_;                    // Universe level to plot
109
  bool color_overlaps_;          // Show overlapping cells?
110
  PlotColorBy color_by_;         // Plot coloring (cell/material)
111
  RGBColor not_found_ {WHITE};   // Plot background color
112
  RGBColor overlap_color_ {RED}; // Plot overlap color
113
  vector<RGBColor> colors_;      // Plot colors
114
};
115

116
typedef xt::xtensor<RGBColor, 2> ImageData;
117

118
struct IdData {
119
  // Constructor
120
  IdData(size_t h_res, size_t v_res);
121

122
  // Methods
123
  void set_value(size_t y, size_t x, const Particle& p, int level);
124
  void set_overlap(size_t y, size_t x);
125

126
  // Members
127
  xt::xtensor<int32_t, 3> data_; //!< 2D array of cell & material ids
128
};
129

130
struct PropertyData {
131
  // Constructor
132
  PropertyData(size_t h_res, size_t v_res);
133

134
  // Methods
135
  void set_value(size_t y, size_t x, const Particle& p, int level);
136
  void set_overlap(size_t y, size_t x);
137

138
  // Members
139
  xt::xtensor<double, 3> data_; //!< 2D array of temperature & density data
140
};
141

142
//===============================================================================
143
// Plot class
144
//===============================================================================
145

146
class SlicePlotBase {
147
public:
148
  template<class T>
149
  T get_map() const;
150

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

153
  // Members
154
public:
155
  Position origin_;           //!< Plot origin in geometry
156
  Position width_;            //!< Plot width in geometry
157
  PlotBasis basis_;           //!< Plot basis (XY/XZ/YZ)
158
  array<size_t, 3> pixels_;   //!< Plot size in pixels
159
  bool slice_color_overlaps_; //!< Show overlapping cells?
160
  int slice_level_ {-1};      //!< Plot universe level
161
private:
162
};
163

164
template<class T>
165
T SlicePlotBase::get_map() const
166
{
167

168
  size_t width = pixels_[0];
169
  size_t height = pixels_[1];
170

171
  // get pixel size
172
  double in_pixel = (width_[0]) / static_cast<double>(width);
173
  double out_pixel = (width_[1]) / static_cast<double>(height);
174

175
  // size data array
176
  T data(width, height);
177

178
  // setup basis indices and initial position centered on pixel
179
  int in_i, out_i;
180
  Position xyz = origin_;
181
  switch (basis_) {
182
  case PlotBasis::xy:
183
    in_i = 0;
184
    out_i = 1;
185
    break;
186
  case PlotBasis::xz:
187
    in_i = 0;
188
    out_i = 2;
189
    break;
190
  case PlotBasis::yz:
191
    in_i = 1;
192
    out_i = 2;
193
    break;
194
  default:
195
    UNREACHABLE();
196
  }
197

198
  // set initial position
199
  xyz[in_i] = origin_[in_i] - width_[0] / 2. + in_pixel / 2.;
200
  xyz[out_i] = origin_[out_i] + width_[1] / 2. - out_pixel / 2.;
201

202
  // arbitrary direction
203
  Direction dir = {0.7071, 0.7071, 0.0};
204

205
#pragma omp parallel
206
  {
207
    Particle p;
208
    p.r() = xyz;
209
    p.u() = dir;
210
    p.coord(0).universe = model::root_universe;
211
    int level = slice_level_;
212
    int j {};
213

214
#pragma omp for
215
    for (int y = 0; y < height; y++) {
216
      p.r()[out_i] = xyz[out_i] - out_pixel * y;
217
      for (int x = 0; x < width; x++) {
218
        p.r()[in_i] = xyz[in_i] + in_pixel * x;
219
        p.n_coord() = 1;
220
        // local variables
221
        bool found_cell = exhaustive_find_cell(p);
222
        j = p.n_coord() - 1;
223
        if (level >= 0) {
224
          j = level;
225
        }
226
        if (found_cell) {
227
          data.set_value(y, x, p, j);
228
        }
229
        if (slice_color_overlaps_ && check_cell_overlap(p, false)) {
230
          data.set_overlap(y, x);
231
        }
232
      } // inner for
233
    }   // outer for
234
  }     // omp parallel
235

236
  return data;
237
}
238

239
// Represents either a voxel or pixel plot
240
class Plot : public PlottableInterface, public SlicePlotBase {
241

242
public:
243
  enum class PlotType { slice = 1, voxel = 2 };
244

245
  Plot(pugi::xml_node plot, PlotType type);
246

247
private:
248
  void set_output_path(pugi::xml_node plot_node);
249
  void set_basis(pugi::xml_node plot_node);
250
  void set_origin(pugi::xml_node plot_node);
251
  void set_width(pugi::xml_node plot_node);
252
  void set_meshlines(pugi::xml_node plot_node);
253

254
public:
255
  // Add mesh lines to ImageData
256
  void draw_mesh_lines(ImageData& data) const;
257
  void create_image() const;
258
  void create_voxel() const;
259

260
  virtual void create_output() const;
261
  virtual void print_info() const;
262

263
  PlotType type_;                 //!< Plot type (Slice/Voxel)
264
  int meshlines_width_;           //!< Width of lines added to the plot
265
  int index_meshlines_mesh_ {-1}; //!< Index of the mesh to draw on the plot
266
  RGBColor meshlines_color_;      //!< Color of meshlines on the plot
267
};
268

269
class ProjectionPlot : public PlottableInterface {
270

271
public:
272
  ProjectionPlot(pugi::xml_node plot);
273

274
  virtual void create_output() const;
275
  virtual void print_info() const;
276

277
private:
278
  void set_output_path(pugi::xml_node plot_node);
279
  void set_look_at(pugi::xml_node node);
280
  void set_camera_position(pugi::xml_node node);
281
  void set_field_of_view(pugi::xml_node node);
282
  void set_pixels(pugi::xml_node node);
283
  void set_opacities(pugi::xml_node node);
284
  void set_orthographic_width(pugi::xml_node node);
285
  void set_wireframe_thickness(pugi::xml_node node);
286
  void set_wireframe_ids(pugi::xml_node node);
287
  void set_wireframe_color(pugi::xml_node node);
288

289
  /* If starting the particle from outside the geometry, we have to
290
   * find a distance to the boundary in a non-standard surface intersection
291
   * check. It's an exhaustive search over surfaces in the top-level universe.
292
   */
293
  static int advance_to_boundary_from_void(Particle& p);
294

295
  /* Checks if a vector of two TrackSegments is equivalent. We define this
296
   * to mean not having matching intersection lengths, but rather having
297
   * a matching sequence of surface/cell/material intersections.
298
   */
299
  struct TrackSegment;
300
  bool trackstack_equivalent(const vector<TrackSegment>& track1,
301
    const vector<TrackSegment>& track2) const;
302

303
  /* Used for drawing wireframe and colors. We record the list of
304
   * surface/cell/material intersections and the corresponding lengths as a ray
305
   * traverses the geometry, then color by iterating in reverse.
306
   */
307
  struct TrackSegment {
308
    int id;        // material or cell ID (which is being colored)
309
    double length; // length of this track intersection
310

311
    /* Recording this allows us to draw edges on the wireframe. For instance
312
     * if two surfaces bound a single cell, it allows drawing that sharp edge
313
     * where the surfaces intersect.
314
     */
315
    int surface; // last surface ID intersected in this segment
316
    TrackSegment(int id_a, double length_a, int surface_a)
317
      : id(id_a), length(length_a), surface(surface_a)
318
    {}
319
  };
320

321
  // Max intersections before we assume ray tracing is caught in an infinite
322
  // loop:
323
  static const int MAX_INTERSECTIONS = 1000000;
324

325
  std::array<int, 2> pixels_;              // pixel dimension of resulting image
326
  double horizontal_field_of_view_ {70.0}; // horiz. f.o.v. in degrees
327
  Position camera_position_;               // where camera is
328
  Position look_at_;             // point camera is centered looking at
329
  Direction up_ {0.0, 0.0, 1.0}; // which way is up
330

331
  // which color IDs should be wireframed. If empty, all cells are wireframed.
332
  vector<int> wireframe_ids_;
333

334
  /* The horizontal thickness, if using an orthographic projection.
335
   * If set to zero, we assume using a perspective projection.
336
   */
337
  double orthographic_width_ {0.0};
338

339
  // Thickness of the wireframe lines. Can set to zero for no wireframe.
340
  int wireframe_thickness_ {1};
341

342
  RGBColor wireframe_color_ {BLACK}; // wireframe color
343
  vector<double> xs_; // macro cross section values for cell volume rendering
344
};
345

346
//===============================================================================
347
// Non-member functions
348
//===============================================================================
349

350
/* Write a PPM image
351
 * filename - name of output file
352
 * data - image data to write
353
 */
354
void output_ppm(const std::string& filename, const ImageData& data);
355

356
#ifdef USE_LIBPNG
357
/* Write a PNG image
358
 * filename - name of output file
359
 * data - image data to write
360
 */
361
void output_png(const std::string& filename, const ImageData& data);
362
#endif
363

364
//! Initialize a voxel file
365
//! \param[in] id of an open hdf5 file
366
//! \param[in] dimensions of the voxel file (dx, dy, dz)
367
//! \param[out] dataspace pointer to voxel data
368
//! \param[out] dataset pointer to voxesl data
369
//! \param[out] pointer to memory space of voxel data
370
void voxel_init(hid_t file_id, const hsize_t* dims, hid_t* dspace, hid_t* dset,
371
  hid_t* memspace);
372

373
//! Write a section of the voxel data to hdf5
374
//! \param[in] voxel slice
375
//! \param[out] dataspace pointer to voxel data
376
//! \param[out] dataset pointer to voxesl data
377
//! \param[out] pointer to data to write
378
void voxel_write_slice(
379
  int x, hid_t dspace, hid_t dset, hid_t memspace, void* buf);
380

381
//! Close voxel file entities
382
//! \param[in] data space to close
383
//! \param[in] dataset to close
384
//! \param[in] memory space to close
385
void voxel_finalize(hid_t dspace, hid_t dset, hid_t memspace);
386

387
//===============================================================================
388
// External functions
389
//===============================================================================
390

391
//! Read plot specifications from a plots.xml file
392
void read_plots_xml();
393

394
//! Read plot specifications from an XML Node
395
//! \param[in] XML node containing plot info
396
void read_plots_xml(pugi::xml_node root);
397

398
//! Clear memory
399
void free_memory_plot();
400

401
//! Create a randomly generated RGB color
402
//! \return RGBColor with random value
403
RGBColor random_color();
404

405
} // namespace openmc
406
#endif // OPENMC_PLOT_H
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc