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

openmc-dev / openmc / 12776996362

14 Jan 2025 09:49PM UTC coverage: 84.938% (+0.2%) from 84.729%
12776996362

Pull #3133

github

web-flow
Merge 0495246d9 into 549cc0973
Pull Request #3133: Kinetics parameters using Iterated Fission Probability

318 of 330 new or added lines in 10 files covered. (96.36%)

1658 existing lines in 66 files now uncovered.

50402 of 59340 relevant lines covered (84.94%)

33987813.96 hits per line

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

79.52
/include/openmc/mesh.h
1
//! \file mesh.h
2
//! \brief Mesh types used for tallies, Shannon entropy, CMFD, etc.
3

4
#ifndef OPENMC_MESH_H
5
#define OPENMC_MESH_H
6

7
#include <unordered_map>
8

9
#include "hdf5.h"
10
#include "pugixml.hpp"
11
#include "xtensor/xtensor.hpp"
12
#include <gsl/gsl-lite.hpp>
13

14
#include "openmc/bounding_box.h"
15
#include "openmc/error.h"
16
#include "openmc/memory.h" // for unique_ptr
17
#include "openmc/particle.h"
18
#include "openmc/position.h"
19
#include "openmc/vector.h"
20
#include "openmc/xml_interface.h"
21

22
#ifdef DAGMC
23
#include "moab/AdaptiveKDTree.hpp"
24
#include "moab/Core.hpp"
25
#include "moab/GeomUtil.hpp"
26
#include "moab/Matrix3.hpp"
27
#endif
28

29
#ifdef LIBMESH
30
#include "libmesh/bounding_box.h"
31
#include "libmesh/dof_map.h"
32
#include "libmesh/elem.h"
33
#include "libmesh/equation_systems.h"
34
#include "libmesh/exodusII_io.h"
35
#include "libmesh/explicit_system.h"
36
#include "libmesh/libmesh.h"
37
#include "libmesh/mesh.h"
38
#include "libmesh/point.h"
39
#endif
40

41
namespace openmc {
42

43
//==============================================================================
44
// Constants
45
//==============================================================================
46

47
enum class ElementType { UNSUPPORTED = -1, LINEAR_TET, LINEAR_HEX };
48

49
//==============================================================================
50
// Global variables
51
//==============================================================================
52

53
extern "C" const bool LIBMESH_ENABLED;
54

55
class Mesh;
56

57
namespace model {
58

59
extern std::unordered_map<int32_t, int32_t> mesh_map;
60
extern vector<unique_ptr<Mesh>> meshes;
61

62
} // namespace model
63

64
#ifdef LIBMESH
65
namespace settings {
66
// used when creating new libMesh::MeshBase instances
67
extern unique_ptr<libMesh::LibMeshInit> libmesh_init;
68
extern const libMesh::Parallel::Communicator* libmesh_comm;
69
} // namespace settings
70
#endif
71

72
class Mesh {
73
public:
74
  // Types, aliases
75
  struct MaterialVolume {
76
    int32_t material; //!< material index
77
    double volume;    //!< volume in [cm^3]
78
  };
79

80
  // Constructors and destructor
81
  Mesh() = default;
472✔
82
  Mesh(pugi::xml_node node);
83
  virtual ~Mesh() = default;
3,234✔
UNCOV
84

×
85
  // Methods
3,234✔
86
  //! Perform any preparation needed to support point location within the mesh
87
  virtual void prepare_for_point_location() {};
88

89
  //! Update a position to the local coordinates of the mesh
2,765✔
90
  virtual void local_coords(Position& r) const {};
91

92
  //! Return a position in the local coordinates of the mesh
1,096,622,704✔
93
  virtual Position local_coords(const Position& r) const { return r; };
94

UNCOV
95
  //! Sample a position within a mesh element
×
96
  //
97
  //! \param[in] bin Bin value of the mesh element sampled
98
  //! \param[inout] seed Seed to use for random sampling
99
  //! \return sampled position within mesh element
100
  virtual Position sample_element(int32_t bin, uint64_t* seed) const = 0;
101

102
  //! Determine which bins were crossed by a particle
103
  //
104
  //! \param[in] r0 Previous position of the particle
105
  //! \param[in] r1 Current position of the particle
106
  //! \param[in] u Particle direction
107
  //! \param[out] bins Bins that were crossed
108
  //! \param[out] lengths Fraction of tracklength in each bin
109
  virtual void bins_crossed(Position r0, Position r1, const Direction& u,
110
    vector<int>& bins, vector<double>& lengths) const = 0;
111

112
  //! Determine which surface bins were crossed by a particle
113
  //
114
  //! \param[in] r0 Previous position of the particle
115
  //! \param[in] r1 Current position of the particle
116
  //! \param[in] u Particle direction
117
  //! \param[out] bins Surface bins that were crossed
118
  virtual void surface_bins_crossed(
119
    Position r0, Position r1, const Direction& u, vector<int>& bins) const = 0;
120

121
  //! Get bin at a given position in space
122
  //
123
  //! \param[in] r Position to get bin for
124
  //! \return Mesh bin
125
  virtual int get_bin(Position r) const = 0;
126

127
  //! Get the number of mesh cells.
128
  virtual int n_bins() const = 0;
129

130
  //! Get the number of mesh cell surfaces.
131
  virtual int n_surface_bins() const = 0;
132

133
  int32_t id() const { return id_; }
134

135
  const std::string& name() const { return name_; }
136

137
  //! Set the mesh ID
138
  void set_id(int32_t id = -1);
139

140
  //! Write the mesh data to an HDF5 group
141
  void to_hdf5(hid_t group) const;
142

143
  //! Write mesh data to an HDF5 group
144
  //
145
  //! \param[in] group HDF5 group
146
  virtual void to_hdf5_inner(hid_t group) const = 0;
147

148
  //! Find the mesh lines that intersect an axis-aligned slice plot
149
  //
150
  //! \param[in] plot_ll The lower-left coordinates of the slice plot.
151
  //! \param[in] plot_ur The upper-right coordinates of the slice plot.
152
  //! \return A pair of vectors indicating where the mesh lines lie along each
153
  //!   of the plot's axes.  For example an xy-slice plot will get back a vector
154
  //!   of x-coordinates and another of y-coordinates.  These vectors may be
155
  //!   empty for low-dimensional meshes.
156
  virtual std::pair<vector<double>, vector<double>> plot(
157
    Position plot_ll, Position plot_ur) const = 0;
158

159
  //! Return a string representation of the mesh bin
160
  //
161
  //! \param[in] bin Mesh bin to generate a label for
162
  virtual std::string bin_label(int bin) const = 0;
163

164
  //! Get the volume of a mesh bin
165
  //
166
  //! \param[in] bin Bin to return the volume for
167
  //! \return Volume of the bin
168
  virtual double volume(int bin) const = 0;
169

170
  //! Volumes of all elements in the mesh in bin ordering
171
  vector<double> volumes() const;
172

173
  virtual std::string get_mesh_type() const = 0;
174

175
  //! Determine volume of materials within a single mesh elemenet
176
  //
177
  //! \param[in] n_sample Number of samples within each element
178
  //! \param[in] bin Index of mesh element
179
  //! \param[out] Array of (material index, volume) for desired element
180
  //! \param[inout] seed Pseudorandom number seed
181
  //! \return Number of materials within element
182
  int material_volumes(int n_sample, int bin, gsl::span<MaterialVolume> volumes,
183
    uint64_t* seed) const;
184

185
  //! Determine volume of materials within a single mesh elemenet
186
  //
187
  //! \param[in] n_sample Number of samples within each element
188
  //! \param[in] bin Index of mesh element
189
  //! \param[inout] seed Pseudorandom number seed
190
  //! \return Vector of (material index, volume) for desired element
191
  vector<MaterialVolume> material_volumes(
192
    int n_sample, int bin, uint64_t* seed) const;
193

194
  //! Determine bounding box of mesh
195
  //
196
  //! \return Bounding box of mesh
197
  BoundingBox bounding_box() const
198
  {
199
    auto ll = this->lower_left();
48✔
200
    auto ur = this->upper_right();
201
    return {ll.x, ur.x, ll.y, ur.y, ll.z, ur.z};
48✔
202
  }
48✔
203

48✔
204
  virtual Position lower_left() const = 0;
205
  virtual Position upper_right() const = 0;
206

207
  // Data members
208
  xt::xtensor<double, 1> lower_left_;  //!< Lower-left coordinates of mesh
209
  xt::xtensor<double, 1> upper_right_; //!< Upper-right coordinates of mesh
210
  int id_ {-1};                        //!< Mesh ID
211
  std::string name_;                   //!< User-specified name
212
  int n_dimension_ {-1};               //!< Number of dimensions
213
};
214

215
class StructuredMesh : public Mesh {
216
public:
217
  StructuredMesh() = default;
218
  StructuredMesh(pugi::xml_node node) : Mesh {node} {};
219
  virtual ~StructuredMesh() = default;
471✔
220

2,717✔
221
  using MeshIndex = std::array<int, 3>;
3,188✔
UNCOV
222

×
223
  struct MeshDistance {
3,188✔
224
    MeshDistance() = default;
225
    MeshDistance(int _index, bool _max_surface, double _distance)
226
      : next_index {_index}, max_surface {_max_surface}, distance {_distance}
227
    {}
228
    int next_index {-1};
229
    bool max_surface {true};
935,230,248✔
230
    double distance {INFTY};
935,230,248✔
231
    bool operator<(const MeshDistance& o) const
935,230,248✔
232
    {
233
      return distance < o.distance;
234
    }
235
  };
2,147,483,647✔
236

237
  Position sample_element(int32_t bin, uint64_t* seed) const override
2,147,483,647✔
238
  {
239
    return sample_element(get_indices_from_bin(bin), seed);
240
  };
241

53,968,212✔
242
  virtual Position sample_element(const MeshIndex& ijk, uint64_t* seed) const;
243

53,968,212✔
244
  int get_bin(Position r) const override;
245

246
  int n_bins() const override;
247

248
  int n_surface_bins() const override;
249

250
  void bins_crossed(Position r0, Position r1, const Direction& u,
251
    vector<int>& bins, vector<double>& lengths) const override;
252

253
  void surface_bins_crossed(Position r0, Position r1, const Direction& u,
254
    vector<int>& bins) const override;
255

256
  //! Determine which cell or surface bins were crossed by a particle
257
  //
258
  //! \param[in] r0 Previous position of the particle
259
  //! \param[in] r1 Current position of the particle
260
  //! \param[in] u Particle direction
261
  //! \param[in] tally Functor that eventually stores the tally data
262
  template<class T>
263
  void raytrace_mesh(
264
    Position r0, Position r1, const Direction& u, T tally) const;
265

266
  //! Count number of bank sites in each mesh bin / energy bin
267
  //
268
  //! \param[in] Pointer to bank sites
269
  //! \param[in] Number of bank sites
270
  //! \param[out] Whether any bank sites are outside the mesh
271
  xt::xtensor<double, 1> count_sites(
272
    const SourceSite* bank, int64_t length, bool* outside) const;
273

274
  //! Get bin given mesh indices
275
  //
276
  //! \param[in] Array of mesh indices
277
  //! \return Mesh bin
278
  virtual int get_bin_from_indices(const MeshIndex& ijk) const;
279

280
  //! Get mesh indices given a position
281
  //
282
  //! \param[in] r Position to get indices for
283
  //! \param[out] in_mesh Whether position is in mesh
284
  //! \return Array of mesh indices
285
  virtual MeshIndex get_indices(Position r, bool& in_mesh) const;
286

287
  //! Get mesh indices corresponding to a mesh bin
288
  //
289
  //! \param[in] bin Mesh bin
290
  //! \return ijk Mesh indices
291
  virtual MeshIndex get_indices_from_bin(int bin) const;
292

293
  //! Get mesh index in a particular direction
294
  //!
295
  //! \param[in] r Coordinate to get index for
296
  //! \param[in] i Direction index
297
  virtual int get_index_in_direction(double r, int i) const = 0;
298

299
  //! Get the coordinate for the mesh grid boundary in the positive direction
300
  //!
301
  //! \param[in] ijk Array of mesh indices
302
  //! \param[in] i Direction index
303
  virtual double positive_grid_boundary(const MeshIndex& ijk, int i) const
304
  {
305
    auto msg =
306
      fmt::format("Attempting to call positive_grid_boundary on a {} mesh.",
UNCOV
307
        get_mesh_type());
×
308
    fatal_error(msg);
309
  };
310

UNCOV
311
  //! Get the coordinate for the mesh grid boundary in the negative direction
×
UNCOV
312
  //!
×
UNCOV
313
  //! \param[in] ijk Array of mesh indices
×
314
  //! \param[in] i Direction index
315
  virtual double negative_grid_boundary(const MeshIndex& ijk, int i) const
316
  {
317
    auto msg =
318
      fmt::format("Attempting to call negative_grid_boundary on a {} mesh.",
UNCOV
319
        get_mesh_type());
×
320
    fatal_error(msg);
321
  };
322

UNCOV
323
  //! Get the closest distance from the coordinate r to the grid surface
×
UNCOV
324
  //! in i direction  that bounds mesh cell ijk and that is larger than l
×
UNCOV
325
  //! The coordinate r does not have to be inside the mesh cell ijk. In
×
326
  //! curved coordinates, multiple crossings of the same surface can happen,
327
  //! these are selected by the parameter l
328
  //!
329
  //! \param[in] ijk Array of mesh indices
330
  //! \param[in] i direction index of grid surface
331
  //! \param[in] r0 position, from where to calculate the distance
332
  //! \param[in] u direction of flight. actual position is r0 + l * u
333
  //! \param[in] l actual chord length
334
  //! \return MeshDistance struct with closest distance, next cell index in
335
  //! i-direction and min/max surface indicator
336
  virtual MeshDistance distance_to_grid_boundary(const MeshIndex& ijk, int i,
337
    const Position& r0, const Direction& u, double l) const = 0;
338

339
  //! Get a label for the mesh bin
340
  std::string bin_label(int bin) const override;
341

342
  //! Get shape as xt::xtensor
343
  xt::xtensor<int, 1> get_x_shape() const;
344

345
  double volume(int bin) const override
346
  {
347
    return this->volume(get_indices_from_bin(bin));
348
  }
349

984,048✔
350
  Position lower_left() const override
351
  {
984,048✔
352
    int n = lower_left_.size();
353
    Position ll {lower_left_[0], 0.0, 0.0};
354
    ll.y = (n >= 2) ? lower_left_[1] : -INFTY;
48✔
355
    ll.z = (n == 3) ? lower_left_[2] : -INFTY;
356
    return ll;
48✔
357
  };
48✔
358

48✔
359
  Position upper_right() const override
48✔
360
  {
48✔
361
    int n = upper_right_.size();
362
    Position ur {upper_right_[0], 0.0, 0.0};
363
    ur.y = (n >= 2) ? upper_right_[1] : INFTY;
48✔
364
    ur.z = (n == 3) ? upper_right_[2] : INFTY;
365
    return ur;
48✔
366
  };
48✔
367

48✔
368
  //! Get the volume of a specified element
48✔
369
  //! \param[in] ijk Mesh index to return the volume for
48✔
370
  //! \return Volume of the bin
371
  virtual double volume(const MeshIndex& ijk) const = 0;
372

373
  // Data members
374
  std::array<int, 3> shape_; //!< Number of mesh elements in each dimension
375

376
protected:
377
};
378

379
class PeriodicStructuredMesh : public StructuredMesh {
380

381
public:
382
  PeriodicStructuredMesh() = default;
383
  PeriodicStructuredMesh(pugi::xml_node node) : StructuredMesh {node} {};
384

385
  void local_coords(Position& r) const override { r -= origin_; };
386

48✔
387
  Position local_coords(const Position& r) const override
718✔
388
  {
389
    return r - origin_;
296,777,796✔
390
  };
UNCOV
391

×
392
  // Data members
UNCOV
393
  Position origin_ {0.0, 0.0, 0.0}; //!< Origin of the mesh
×
394
};
395

396
//==============================================================================
397
//! Tessellation of n-dimensional Euclidean space by congruent squares or cubes
398
//==============================================================================
399

400
class RegularMesh : public StructuredMesh {
401
public:
402
  // Constructors
403
  RegularMesh() = default;
404
  RegularMesh(pugi::xml_node node);
405

406
  // Overridden methods
407
  int get_index_in_direction(double r, int i) const override;
349✔
408

409
  virtual std::string get_mesh_type() const override;
410

411
  static const std::string mesh_type;
412

413
  MeshDistance distance_to_grid_boundary(const MeshIndex& ijk, int i,
414
    const Position& r0, const Direction& u, double l) const override;
415

416
  std::pair<vector<double>, vector<double>> plot(
417
    Position plot_ll, Position plot_ur) const override;
418

419
  void to_hdf5_inner(hid_t group) const override;
420

421
  //! Get the coordinate for the mesh grid boundary in the positive direction
422
  //!
423
  //! \param[in] ijk Array of mesh indices
424
  //! \param[in] i Direction index
425
  double positive_grid_boundary(const MeshIndex& ijk, int i) const override;
426

427
  //! Get the coordinate for the mesh grid boundary in the negative direction
428
  //!
429
  //! \param[in] ijk Array of mesh indices
430
  //! \param[in] i Direction index
431
  double negative_grid_boundary(const MeshIndex& ijk, int i) const override;
432

433
  //! Count number of bank sites in each mesh bin / energy bin
434
  //
435
  //! \param[in] bank Array of bank sites
436
  //! \param[out] Whether any bank sites are outside the mesh
437
  //! \return Array indicating number of sites in each mesh/energy bin
438
  xt::xtensor<double, 1> count_sites(
439
    const SourceSite* bank, int64_t length, bool* outside) const;
440

441
  //! Return the volume for a given mesh index
442
  double volume(const MeshIndex& ijk) const override;
443

444
  // Data members
445
  double volume_frac_;           //!< Volume fraction of each mesh element
446
  double element_volume_;        //!< Volume of each mesh element
447
  xt::xtensor<double, 1> width_; //!< Width of each mesh element
448
};
449

450
class RectilinearMesh : public StructuredMesh {
451
public:
452
  // Constructors
453
  RectilinearMesh() = default;
454
  RectilinearMesh(pugi::xml_node node);
455

456
  // Overridden methods
457
  int get_index_in_direction(double r, int i) const override;
74✔
458

459
  virtual std::string get_mesh_type() const override;
460

461
  static const std::string mesh_type;
462

463
  MeshDistance distance_to_grid_boundary(const MeshIndex& ijk, int i,
464
    const Position& r0, const Direction& u, double l) const override;
465

466
  std::pair<vector<double>, vector<double>> plot(
467
    Position plot_ll, Position plot_ur) const override;
468

469
  void to_hdf5_inner(hid_t group) const override;
470

471
  //! Get the coordinate for the mesh grid boundary in the positive direction
472
  //!
473
  //! \param[in] ijk Array of mesh indices
474
  //! \param[in] i Direction index
475
  double positive_grid_boundary(const MeshIndex& ijk, int i) const override;
476

477
  //! Get the coordinate for the mesh grid boundary in the negative direction
478
  //!
479
  //! \param[in] ijk Array of mesh indices
480
  //! \param[in] i Direction index
481
  double negative_grid_boundary(const MeshIndex& ijk, int i) const override;
482

483
  //! Return the volume for a given mesh index
484
  double volume(const MeshIndex& ijk) const override;
485

486
  int set_grid();
487

488
  // Data members
489
  array<vector<double>, 3> grid_;
490
};
491

492
class CylindricalMesh : public PeriodicStructuredMesh {
493
public:
494
  // Constructors
495
  CylindricalMesh() = default;
496
  CylindricalMesh(pugi::xml_node node);
497

498
  // Overridden methods
499
  virtual MeshIndex get_indices(Position r, bool& in_mesh) const override;
24✔
500

501
  int get_index_in_direction(double r, int i) const override;
502

503
  virtual std::string get_mesh_type() const override;
504

505
  static const std::string mesh_type;
506

507
  Position sample_element(const MeshIndex& ijk, uint64_t* seed) const override;
508

509
  MeshDistance distance_to_grid_boundary(const MeshIndex& ijk, int i,
510
    const Position& r0, const Direction& u, double l) const override;
511

512
  std::pair<vector<double>, vector<double>> plot(
513
    Position plot_ll, Position plot_ur) const override;
514

515
  void to_hdf5_inner(hid_t group) const override;
516

517
  double volume(const MeshIndex& ijk) const override;
518

519
  // grid accessors
520
  double r(int i) const { return grid_[0][i]; }
521
  double phi(int i) const { return grid_[1][i]; }
522
  double z(int i) const { return grid_[2][i]; }
523

524
  int set_grid();
1,632,000✔
525

1,632,000✔
526
  // Data members
1,632,000✔
527
  array<vector<double>, 3> grid_;
528

529
private:
530
  double find_r_crossing(
531
    const Position& r, const Direction& u, double l, int shell) const;
532
  double find_phi_crossing(
533
    const Position& r, const Direction& u, double l, int shell) const;
534
  StructuredMesh::MeshDistance find_z_crossing(
535
    const Position& r, const Direction& u, double l, int shell) const;
536

537
  bool full_phi_ {false};
538

539
  inline int sanitize_angular_index(int idx, bool full, int N) const
540
  {
541
    if ((idx > 0) and (idx <= N)) {
542
      return idx;
543
    } else if (full) {
161,794,704✔
544
      return (idx + N - 1) % N + 1;
545
    } else {
161,794,704✔
546
      return 0;
125,524,428✔
547
    }
36,270,276✔
548
  }
36,241,476✔
549

550
  inline int sanitize_phi(int idx) const
28,800✔
551
  {
552
    return sanitize_angular_index(idx, full_phi_, shape_[1]);
553
  }
554
};
161,794,704✔
555

556
class SphericalMesh : public PeriodicStructuredMesh {
161,794,704✔
557
public:
558
  // Constructors
559
  SphericalMesh() = default;
560
  SphericalMesh(pugi::xml_node node);
561

562
  // Overridden methods
563
  virtual MeshIndex get_indices(Position r, bool& in_mesh) const override;
24✔
564

565
  int get_index_in_direction(double r, int i) const override;
566

567
  virtual std::string get_mesh_type() const override;
568

569
  static const std::string mesh_type;
570

571
  Position sample_element(const MeshIndex& ijk, uint64_t* seed) const override;
572

573
  MeshDistance distance_to_grid_boundary(const MeshIndex& ijk, int i,
574
    const Position& r0, const Direction& u, double l) const override;
575

576
  std::pair<vector<double>, vector<double>> plot(
577
    Position plot_ll, Position plot_ur) const override;
578

579
  void to_hdf5_inner(hid_t group) const override;
580

581
  double r(int i) const { return grid_[0][i]; }
582
  double theta(int i) const { return grid_[1][i]; }
583
  double phi(int i) const { return grid_[2][i]; }
584

585
  int set_grid();
2,880,000✔
586

2,880,000✔
587
  // Data members
2,880,000✔
588
  array<vector<double>, 3> grid_;
589

590
private:
591
  double find_r_crossing(
592
    const Position& r, const Direction& u, double l, int shell) const;
593
  double find_theta_crossing(
594
    const Position& r, const Direction& u, double l, int shell) const;
595
  double find_phi_crossing(
596
    const Position& r, const Direction& u, double l, int shell) const;
597

598
  bool full_theta_ {false};
599
  bool full_phi_ {false};
600

601
  inline int sanitize_angular_index(int idx, bool full, int N) const
602
  {
603
    if ((idx > 0) and (idx <= N)) {
604
      return idx;
605
    } else if (full) {
465,565,800✔
606
      return (idx + N - 1) % N + 1;
607
    } else {
465,565,800✔
608
      return 0;
300,299,328✔
609
    }
165,266,472✔
610
  }
165,208,872✔
611

612
  double volume(const MeshIndex& ijk) const override;
57,600✔
613

614
  inline int sanitize_theta(int idx) const
615
  {
616
    return sanitize_angular_index(idx, full_theta_, shape_[1]);
617
  }
618
  inline int sanitize_phi(int idx) const
231,089,148✔
619
  {
620
    return sanitize_angular_index(idx, full_phi_, shape_[2]);
231,089,148✔
621
  }
622
};
234,476,652✔
623

624
// Abstract class for unstructured meshes
234,476,652✔
625
class UnstructuredMesh : public Mesh {
626

627
public:
628
  // Constructors
629
  UnstructuredMesh() {};
630
  UnstructuredMesh(pugi::xml_node node);
631
  UnstructuredMesh(const std::string& filename);
632

633
  static const std::string mesh_type;
1✔
634
  virtual std::string get_mesh_type() const override;
635

636
  // Overridden Methods
637

638
  void surface_bins_crossed(Position r0, Position r1, const Direction& u,
639
    vector<int>& bins) const override;
640

641
  void to_hdf5_inner(hid_t group) const override;
642

643
  std::string bin_label(int bin) const override;
644

645
  // Methods
646

647
  //! Add a variable to the mesh instance
648
  virtual void add_score(const std::string& var_name) = 0;
649

650
  //! Remove tally data from the instance
651
  virtual void remove_scores() = 0;
652

653
  //! Set the value of a bin for a variable on the internal
654
  //  mesh instance
655
  virtual void set_score_data(const std::string& var_name,
656
    const vector<double>& values, const vector<double>& std_dev) = 0;
657

658
  //! Write the unstructured mesh to file
659
  //
660
  //! \param[in] filename Base of the file to write
661
  virtual void write(const std::string& base_filename) const = 0;
662

663
  //! Retrieve a centroid for the mesh cell
664
  //
665
  //! \param[in] bin Bin to return the centroid for
666
  //! \return The centroid of the bin
667
  virtual Position centroid(int bin) const = 0;
668

669
  //! Get the number of vertices in the mesh
670
  //
671
  //! \return Number of vertices
672
  virtual int n_vertices() const = 0;
673

674
  //! Retrieve a vertex of the mesh
675
  //
676
  //! \param[in] vertex ID
677
  //! \return vertex coordinates
678
  virtual Position vertex(int id) const = 0;
679

680
  //! Retrieve connectivity of a mesh element
681
  //
682
  //! \param[in] element ID
683
  //! \return element connectivity as IDs of the vertices
684
  virtual std::vector<int> connectivity(int id) const = 0;
685

686
  //! Get the library used for this unstructured mesh
687
  virtual std::string library() const = 0;
688

689
  // Data members
690
  bool output_ {
691
    true}; //!< Write tallies onto the unstructured mesh at the end of a run
692
  std::string filename_; //!< Path to unstructured mesh file
693

694
  ElementType element_type(int bin) const;
695

696
  Position lower_left() const override
697
  {
698
    return {lower_left_[0], lower_left_[1], lower_left_[2]};
699
  }
UNCOV
700
  Position upper_right() const override
×
701
  {
UNCOV
702
    return {upper_right_[0], upper_right_[1], upper_right_[2]};
×
703
  }
UNCOV
704

×
705
protected:
UNCOV
706
  //! Set the length multiplier to apply to each point in the mesh
×
707
  void set_length_multiplier(const double length_multiplier);
708

709
  //! Sample barycentric coordinates given a seed and the vertex positions and
710
  //! return the sampled position
711
  //
712
  //! \param[in] coords Coordinates of the tetrahedron
713
  //! \param[in] seed Random number generation seed
714
  //! \return Sampled position within the tetrahedron
715
  Position sample_tet(std::array<Position, 4> coords, uint64_t* seed) const;
716

717
  // Data members
718
  double length_multiplier_ {
719
    -1.0};              //!< Multiplicative factor applied to mesh coordinates
720
  std::string options_; //!< Options for search data structures
721

722
  //! Determine lower-left and upper-right bounds of mesh
723
  void determine_bounds();
724

725
private:
726
  //! Setup method for the mesh. Builds data structures,
727
  //! sets up element mapping, creates bounding boxes, etc.
728
  virtual void initialize() = 0;
729
};
730

731
#ifdef DAGMC
732

733
class MOABMesh : public UnstructuredMesh {
734
public:
735
  // Constructors
736
  MOABMesh() = default;
737
  MOABMesh(pugi::xml_node);
738
  MOABMesh(const std::string& filename, double length_multiplier = 1.0);
739
  MOABMesh(std::shared_ptr<moab::Interface> external_mbi);
740

741
  static const std::string mesh_lib_type;
742

743
  // Overridden Methods
744

745
  //! Perform any preparation needed to support use in mesh filters
746
  void prepare_for_point_location() override;
747

748
  Position sample_element(int32_t bin, uint64_t* seed) const override;
749

750
  void bins_crossed(Position r0, Position r1, const Direction& u,
751
    vector<int>& bins, vector<double>& lengths) const override;
752

753
  int get_bin(Position r) const override;
754

755
  int n_bins() const override;
756

757
  int n_surface_bins() const override;
758

759
  std::pair<vector<double>, vector<double>> plot(
760
    Position plot_ll, Position plot_ur) const override;
761

762
  std::string library() const override;
763

764
  //! Add a score to the mesh instance
765
  void add_score(const std::string& score) override;
766

767
  //! Remove all scores from the mesh instance
768
  void remove_scores() override;
769

770
  //! Set data for a score
771
  void set_score_data(const std::string& score, const vector<double>& values,
772
    const vector<double>& std_dev) override;
773

774
  //! Write the mesh with any current tally data
775
  void write(const std::string& base_filename) const override;
776

777
  Position centroid(int bin) const override;
778

779
  int n_vertices() const override;
780

781
  Position vertex(int id) const override;
782

783
  std::vector<int> connectivity(int id) const override;
784

785
  //! Get the volume of a mesh bin
786
  //
787
  //! \param[in] bin Bin to return the volume for
788
  //! \return Volume of the bin
789
  double volume(int bin) const override;
790

791
private:
792
  void initialize() override;
793

794
  // Methods
795

796
  //! Create the MOAB interface pointer
797
  void create_interface();
798

799
  //! Find all intersections with faces of the mesh.
800
  //
801
  //! \param[in] start Staring location
802
  //! \param[in] dir Normalized particle direction
803
  //! \param[in] track_len length of particle track
804
  //! \param[out] Mesh intersections
805
  void intersect_track(const moab::CartVect& start, const moab::CartVect& dir,
806
    double track_len, vector<double>& hits) const;
807

808
  //! Calculate the volume for a given tetrahedron handle.
809
  //
810
  // \param[in] tet MOAB EntityHandle of the tetrahedron
811
  double tet_volume(moab::EntityHandle tet) const;
812

813
  //! Find the tetrahedron for the given location if
814
  //! one exists
815
  //
816
  //! \param[in]
817
  //! \return MOAB EntityHandle of tet
818
  moab::EntityHandle get_tet(const Position& r) const;
819

820
  //! Return the containing tet given a position
821
  moab::EntityHandle get_tet(const moab::CartVect& r) const
822
  {
823
    return get_tet(Position(r[0], r[1], r[2]));
824
  };
825

826
  //! Check for point containment within a tet; uses
827
  //! pre-computed barycentric data.
828
  //
829
  //! \param[in] r Position to check
830
  //! \param[in] MOAB terahedron to check
831
  //! \return True if r is inside, False if r is outside
832
  bool point_in_tet(const moab::CartVect& r, moab::EntityHandle tet) const;
833

834
  //! Compute barycentric coordinate data for all tetrahedra
835
  //! in the mesh.
836
  //
837
  //! \param[in] tets MOAB Range of tetrahedral elements
838
  void compute_barycentric_data(const moab::Range& tets);
839

840
  //! Translate a MOAB EntityHandle to its corresponding bin.
841
  //
842
  //! \param[in] eh MOAB EntityHandle to translate
843
  //! \return Mesh bin
844
  int get_bin_from_ent_handle(moab::EntityHandle eh) const;
845

846
  //! Translate a bin to its corresponding MOAB EntityHandle
847
  //! for the tetrahedron representing that bin.
848
  //
849
  //! \param[in] bin Bin value to translate
850
  //! \return MOAB EntityHandle of tet
851
  moab::EntityHandle get_ent_handle_from_bin(int bin) const;
852

853
  //! Get a vertex index into the global range from a handle
854
  int get_vert_idx_from_handle(moab::EntityHandle vert) const;
855

856
  //! Get the bin for a given mesh cell index
857
  //
858
  //! \param[in] idx Index of the mesh cell.
859
  //! \return Mesh bin
860
  int get_bin_from_index(int idx) const;
861

862
  //! Get the mesh cell index for a given position
863
  //
864
  //! \param[in] r Position to get index for
865
  //! \param[in,out] in_mesh Whether position is in the mesh
866
  int get_index(const Position& r, bool* in_mesh) const;
867

868
  //! Get the mesh cell index from a bin
869
  //
870
  //! \param[in] bin Bin to get the index for
871
  //! \return Index of the bin
872
  int get_index_from_bin(int bin) const;
873

874
  //! Build a KDTree for all tetrahedra in the mesh. All
875
  //! triangles representing 2D faces of the mesh are
876
  //! added to the tree as well.
877
  //
878
  //! \param[in] all_tets MOAB Range of tetrahedra for the tree
879
  void build_kdtree(const moab::Range& all_tets);
880

881
  //! Get the tags for a score from the mesh instance
882
  //! or create them if they are not there
883
  //
884
  //! \param[in] score Name of the score
885
  //! \return The MOAB value and error tag handles, respectively
886
  std::pair<moab::Tag, moab::Tag> get_score_tags(std::string score) const;
887

888
  // Data members
889
  moab::Range ehs_;   //!< Range of tetrahedra EntityHandle's in the mesh
890
  moab::Range verts_; //!< Range of vertex EntityHandle's in the mesh
891
  moab::EntityHandle tetset_;      //!< EntitySet containing all tetrahedra
892
  moab::EntityHandle kdtree_root_; //!< Root of the MOAB KDTree
893
  std::shared_ptr<moab::Interface> mbi_;    //!< MOAB instance
894
  unique_ptr<moab::AdaptiveKDTree> kdtree_; //!< MOAB KDTree instance
895
  vector<moab::Matrix3> baryc_data_;        //!< Barycentric data for tetrahedra
896
  vector<std::string> tag_names_; //!< Names of score tags added to the mesh
897
};
898

899
#endif
900

901
#ifdef LIBMESH
902

903
class LibMesh : public UnstructuredMesh {
904
public:
905
  // Constructors
906
  LibMesh(pugi::xml_node node);
907
  LibMesh(const std::string& filename, double length_multiplier = 1.0);
908
  LibMesh(libMesh::MeshBase& input_mesh, double length_multiplier = 1.0);
909

910
  static const std::string mesh_lib_type;
911

912
  // Overridden Methods
913
  void bins_crossed(Position r0, Position r1, const Direction& u,
914
    vector<int>& bins, vector<double>& lengths) const override;
915

916
  Position sample_element(int32_t bin, uint64_t* seed) const override;
917

918
  int get_bin(Position r) const override;
919

920
  int n_bins() const override;
921

922
  int n_surface_bins() const override;
923

924
  std::pair<vector<double>, vector<double>> plot(
925
    Position plot_ll, Position plot_ur) const override;
926

927
  std::string library() const override;
928

929
  void add_score(const std::string& var_name) override;
930

931
  void remove_scores() override;
932

933
  void set_score_data(const std::string& var_name, const vector<double>& values,
934
    const vector<double>& std_dev) override;
935

936
  void write(const std::string& base_filename) const override;
937

938
  Position centroid(int bin) const override;
939

940
  int n_vertices() const override;
941

942
  Position vertex(int id) const override;
943

944
  std::vector<int> connectivity(int id) const override;
945

946
  //! Get the volume of a mesh bin
947
  //
948
  //! \param[in] bin Bin to return the volume for
949
  //! \return Volume of the bin
950
  double volume(int bin) const override;
951

952
  libMesh::MeshBase* mesh_ptr() const { return m_; };
953

954
private:
955
  void initialize() override;
956
  void set_mesh_pointer_from_filename(const std::string& filename);
957
  void build_eqn_sys();
958

959
  // Methods
960

961
  //! Translate a bin value to an element reference
962
  const libMesh::Elem& get_element_from_bin(int bin) const;
963

964
  //! Translate an element pointer to a bin index
965
  int get_bin_from_element(const libMesh::Elem* elem) const;
966

967
  // Data members
968
  unique_ptr<libMesh::MeshBase> unique_m_ =
969
    nullptr; //!< pointer to the libMesh MeshBase instance, only used if mesh is
970
             //!< created inside OpenMC
971
  libMesh::MeshBase* m_; //!< pointer to libMesh MeshBase instance, always set
972
                         //!< during intialization
973
  vector<unique_ptr<libMesh::PointLocatorBase>>
974
    pl_; //!< per-thread point locators
975
  unique_ptr<libMesh::EquationSystems>
976
    equation_systems_; //!< pointer to the libMesh EquationSystems
977
                       //!< instance
978
  std::string
979
    eq_system_name_; //!< name of the equation system holding OpenMC results
980
  std::unordered_map<std::string, unsigned int>
981
    variable_map_; //!< mapping of variable names (tally scores) to libMesh
982
                   //!< variable numbers
983
  libMesh::BoundingBox bbox_; //!< bounding box of the mesh
984
  libMesh::dof_id_type
985
    first_element_id_; //!< id of the first element in the mesh
986

987
  const bool adaptive_; //!< whether this mesh has adaptivity enabled or not
988
  std::vector<libMesh::dof_id_type>
989
    bin_to_elem_map_; //!< mapping bin indices to dof indices for active
990
                      //!< elements
991
  std::vector<int> elem_to_bin_map_; //!< mapping dof indices to bin indices for
992
                                     //!< active elements
993
};
994

995
#endif
996

997
//==============================================================================
998
// Non-member functions
999
//==============================================================================
1000

1001
//! Read meshes from either settings/tallies
1002
//
1003
//! \param[in] root XML node
1004
void read_meshes(pugi::xml_node root);
1005

1006
//! Write mesh data to an HDF5 group
1007
//
1008
//! \param[in] group HDF5 group
1009
void meshes_to_hdf5(hid_t group);
1010

1011
void free_memory_mesh();
1012

1013
} // namespace openmc
1014

1015
#endif // OPENMC_MESH_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