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

openmc-dev / openmc / 12957335491

24 Jan 2025 08:45PM UTC coverage: 84.833% (-0.1%) from 84.928%
12957335491

Pull #3275

github

web-flow
Merge 5f7272d6d into 708978002
Pull Request #3275: Added missing documentation

50070 of 59022 relevant lines covered (84.83%)

34780830.76 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 <cmath>
5
#include <sstream>
6
#include <unordered_map>
7

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

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

21
namespace openmc {
22

23
//===============================================================================
24
// Global variables
25
//===============================================================================
26

27
class PlottableInterface;
28

29
namespace model {
30

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

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

37
} // namespace model
38

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

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

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

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

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

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

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

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

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

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

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

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

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

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

118
typedef xt::xtensor<RGBColor, 2> ImageData;
119

120
struct IdData {
121
  // Constructor
122
  IdData(size_t h_res, size_t v_res);
123

124
  // Methods
125
  void set_value(size_t y, size_t x, const GeometryState& p, int level);
126
  void set_overlap(size_t y, size_t x);
127

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

132
struct PropertyData {
133
  // Constructor
134
  PropertyData(size_t h_res, size_t v_res);
135

136
  // Methods
137
  void set_value(size_t y, size_t x, const GeometryState& p, int level);
138
  void set_overlap(size_t y, size_t x);
139

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

144
//===============================================================================
145
// Plot class
146
//===============================================================================
147

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

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

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

166
template<class T>
167
T SlicePlotBase::get_map() const
168
{
169

170
  size_t width = pixels_[0];
171
  size_t height = pixels_[1];
172

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

177
  // size data array
178
  T data(width, height);
179

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

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

204
  // arbitrary direction
205
  Direction dir = {1. / std::sqrt(2.), 1. / std::sqrt(2.), 0.0};
206

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

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

238
  return data;
239
}
240

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

244
public:
245
  enum class PlotType { slice = 1, voxel = 2 };
246

247
  Plot(pugi::xml_node plot, PlotType type);
248

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

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

262
  virtual void create_output() const;
263
  virtual void print_info() const;
264

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

271
class ProjectionPlot : public PlottableInterface {
272

273
public:
274
  ProjectionPlot(pugi::xml_node plot);
275

276
  virtual void create_output() const;
277
  virtual void print_info() const;
278

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

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

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

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

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

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

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

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

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

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

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

348
//===============================================================================
349
// Non-member functions
350
//===============================================================================
351

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

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

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

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

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

389
//===============================================================================
390
// External functions
391
//===============================================================================
392

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

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

400
//! Clear memory
401
void free_memory_plot();
402

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

407
} // namespace openmc
408
#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

© 2025 Coveralls, Inc