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

openmc-dev / openmc / 7188607138

12 Dec 2023 11:37PM UTC coverage: 84.57% (-0.2%) from 84.738%
7188607138

push

github

web-flow
added check to length of input args for IndependantOperator (#2799)

Co-authored-by: Paul Romano <paul.k.romano@gmail.com>

4 of 4 new or added lines in 1 file covered. (100.0%)

92 existing lines in 18 files now uncovered.

47388 of 56034 relevant lines covered (84.57%)

33876484.43 hits per line

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

86.25
/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) {};
15,896,849✔
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)
392✔
49
  {
392✔
50
    if (v.size() != 3) {
392✔
UNCOV
51
      throw std::out_of_range("Incorrect vector size for RGBColor.");
×
52
    }
53
    red = v[0];
392✔
54
    green = v[1];
392✔
55
    blue = v[2];
392✔
56
  }
392✔
57

58
  bool operator==(const RGBColor& other)
6,358✔
59
  {
60
    return red == other.red && green == other.green && blue == other.blue;
6,358✔
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

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

105
  // Public color-related data
106
  PlottableInterface(pugi::xml_node plot_node);
107
  virtual ~PlottableInterface() = default;
912✔
UNCOV
108
  int level_;                    // Universe level to plot
×
109
  bool color_overlaps_;          // Show overlapping cells?
912✔
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

6,314✔
168
  size_t width = pixels_[0];
169
  size_t height = pixels_[1];
170

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

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

178
  // setup basis indices and initial position centered on pixel
6,314✔
179
  int in_i, out_i;
180
  Position xyz = origin_;
181
  switch (basis_) {
182
  case PlotBasis::xy:
6,314✔
183
    in_i = 0;
6,314✔
184
    out_i = 1;
6,202✔
185
    break;
6,202✔
186
  case PlotBasis::xz:
6,202✔
187
    in_i = 0;
6,202✔
188
    out_i = 2;
56✔
189
    break;
56✔
190
  case PlotBasis::yz:
56✔
191
    in_i = 1;
56✔
192
    out_i = 2;
56✔
193
    break;
56✔
194
  default:
56✔
195
    UNREACHABLE();
56✔
UNCOV
196
  }
×
UNCOV
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

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

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

3,608✔
214
#pragma omp for
3,608✔
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++) {
687,416✔
218
        p.r()[in_i] = xyz[in_i] + in_pixel * x;
683,808✔
219
        p.n_coord() = 1;
136,329,552✔
220
        // local variables
135,645,744✔
221
        bool found_cell = exhaustive_find_cell(p);
135,645,744✔
222
        j = p.n_coord() - 1;
223
        if (level >= 0) {
135,645,744✔
224
          j = level;
135,645,744✔
225
        }
135,645,744✔
226
        if (found_cell) {
227
          data.set_value(y, x, p, j);
228
        }
135,645,744✔
229
        if (slice_color_overlaps_ && check_cell_overlap(p, false)) {
26,003,024✔
230
          data.set_overlap(y, x);
231
        }
135,645,744✔
232
      } // inner for
20,544✔
233
    }   // outer for
234
  }     // omp parallel
235

236
  return data;
3,608✔
237
}
238

12,628✔
UNCOV
239
// Represents either a voxel or pixel plot
×
240
class Plot : public PlottableInterface, public SlicePlotBase {
14✔
241

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

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

247
private:
14✔
248
  void set_output_path(pugi::xml_node plot_node);
14✔
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);
14✔
252
  void set_meshlines(pugi::xml_node plot_node);
253

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

14✔
260
  virtual void create_output() const;
14✔
UNCOV
261
  virtual void print_info() const;
×
UNCOV
262

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

×
UNCOV
269
class ProjectionPlot : public PlottableInterface {
×
UNCOV
270

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

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

277
private:
278
  void set_output_path(pugi::xml_node plot_node);
14✔
279
  void set_look_at(pugi::xml_node node);
280
  void set_camera_position(pugi::xml_node node);
6✔
281
  void set_field_of_view(pugi::xml_node node);
282
  void set_pixels(pugi::xml_node node);
8✔
283
  void set_opacities(pugi::xml_node node);
8✔
284
  void set_orthographic_width(pugi::xml_node node);
8✔
285
  void set_wireframe_thickness(pugi::xml_node node);
8✔
286
  void set_wireframe_ids(pugi::xml_node node);
8✔
287
  void set_wireframe_color(pugi::xml_node node);
8✔
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
32✔
291
   * check. It's an exhaustive search over surfaces in the top-level universe.
24✔
292
   */
96✔
293
  static int advance_to_boundary_from_void(Particle& p);
72✔
294

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

72✔
303
  /* Used for drawing wireframe and colors. We record the list of
304
   * surface/cell/material intersections and the corresponding lengths as a ray
72✔
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
8✔
310

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

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

6,300✔
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
6,300✔
329
  Direction up_ {0.0, 0.0, 1.0}; // which way is up
6,300✔
330

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

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

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

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

346
//===============================================================================
347
// Non-member functions
6,300✔
348
//===============================================================================
6,300✔
349

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

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

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

373
//! Write a section of the voxel data to hdf5
374
//! \param[in] voxel slice
135,645,672✔
375
//! \param[out] dataspace pointer to voxel data
26,002,952✔
376
//! \param[out] dataset pointer to voxesl data
377
//! \param[out] pointer to data to write
135,645,672✔
378
void voxel_write_slice(
20,544✔
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
3,600✔
383
//! \param[in] dataset to close
384
//! \param[in] memory space to close
12,600✔
UNCOV
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