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

openmc-dev / openmc / 19058781736

04 Nov 2025 05:26AM UTC coverage: 82.008% (-3.1%) from 85.155%
19058781736

Pull #3252

github

web-flow
Merge b8a72730f into bd76fc056
Pull Request #3252: Adding vtkhdf option to write vtk data

16714 of 23236 branches covered (71.93%)

Branch coverage included in aggregate %.

61 of 66 new or added lines in 1 file covered. (92.42%)

3175 existing lines in 103 files now uncovered.

54243 of 63288 relevant lines covered (85.71%)

43393337.77 hits per line

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

60.31
/src/tallies/filter_meshmaterial.cpp
1
#include "openmc/tallies/filter_meshmaterial.h"
2

3
#include <utility> // for move
4

5
#include <fmt/core.h>
6

7
#include "openmc/capi.h"
8
#include "openmc/constants.h"
9
#include "openmc/container_util.h"
10
#include "openmc/error.h"
11
#include "openmc/material.h"
12
#include "openmc/mesh.h"
13
#include "openmc/xml_interface.h"
14

15
namespace openmc {
16

17
void MeshMaterialFilter::from_xml(pugi::xml_node node)
22✔
18
{
19
  // Get mesh ID
20
  auto mesh = get_node_array<int32_t>(node, "mesh");
22✔
21
  if (mesh.size() != 1) {
22!
22
    fatal_error(
×
23
      "Only one mesh can be specified per " + type_str() + " mesh filter.");
×
24
  }
25

26
  auto id = mesh[0];
22✔
27
  auto search = model::mesh_map.find(id);
22✔
28
  if (search == model::mesh_map.end()) {
22!
29
    fatal_error(
×
30
      fmt::format("Could not find mesh {} specified on tally filter.", id));
×
31
  }
32
  set_mesh(search->second);
22✔
33

34
  // Get pairs of (element index, material) and set the bins
35
  auto bins = get_node_array<int32_t>(node, "bins");
22✔
36
  this->set_bins(bins);
22✔
37

38
  if (check_for_node(node, "translation")) {
22!
39
    set_translation(get_node_array<double>(node, "translation"));
×
40
  }
41
}
22✔
42

43
void MeshMaterialFilter::set_bins(span<int32_t> bins)
22✔
44
{
45
  if (bins.size() % 2 != 0) {
22!
46
    fatal_error(
×
47
      fmt::format("Size of mesh material bins is not even: {}", bins.size()));
×
48
  }
49

50
  // Create a vector of ElementMat pairs from the flat vector of bins
51
  vector<ElementMat> element_mats;
22✔
52
  for (int64_t i = 0; i < bins.size() / 2; ++i) {
132✔
53
    int32_t element = bins[2 * i];
110✔
54
    int32_t mat_id = bins[2 * i + 1];
110✔
55
    auto search = model::material_map.find(mat_id);
110✔
56
    if (search == model::material_map.end()) {
110!
57
      fatal_error(fmt::format(
×
58
        "Could not find material {} specified on tally filter.", mat_id));
59
    }
60
    int32_t mat_index = search->second;
110✔
61
    element_mats.push_back({element, mat_index});
110✔
62
  }
63

64
  this->set_bins(std::move(element_mats));
22✔
65
}
22✔
66

67
void MeshMaterialFilter::set_bins(vector<ElementMat>&& bins)
22✔
68
{
69
  // Swap internal bins_ with the provided vector to avoid copying
70
  bins_.swap(bins);
22✔
71

72
  // Clear and update the mapping and vector of materials
73
  materials_.clear();
22✔
74
  map_.clear();
22✔
75
  for (std::size_t i = 0; i < bins_.size(); ++i) {
132✔
76
    const auto& x = bins_[i];
110✔
77
    assert(x.index_mat >= 0);
90!
78
    assert(x.index_mat < model::materials.size());
90!
79
    materials_.insert(x.index_mat);
110✔
80
    map_[x] = i;
110✔
81
  }
82

83
  n_bins_ = bins_.size();
22✔
84
}
22✔
85

86
void MeshMaterialFilter::set_mesh(int32_t mesh)
22✔
87
{
88
  // perform any additional perparation for mesh tallies here
89
  mesh_ = mesh;
22✔
90
  model::meshes[mesh_]->prepare_for_point_location();
22✔
91
}
22✔
92

93
void MeshMaterialFilter::set_translation(const Position& translation)
×
94
{
95
  translated_ = true;
×
96
  translation_ = translation;
×
UNCOV
97
}
×
98

99
void MeshMaterialFilter::set_translation(const double translation[3])
×
100
{
101
  this->set_translation({translation[0], translation[1], translation[2]});
×
UNCOV
102
}
×
103

104
void MeshMaterialFilter::get_all_bins(
7,834,013✔
105
  const Particle& p, TallyEstimator estimator, FilterMatch& match) const
106
{
107
  // If current material is not in any bins, don't bother checking
108
  if (!contains(materials_, p.material())) {
7,834,013!
109
    return;
×
110
  }
111

112
  Position last_r = p.r_last();
7,834,013✔
113
  Position r = p.r();
7,834,013✔
114
  Position u = p.u();
7,834,013✔
115

116
  // apply translation if present
117
  if (translated_) {
7,834,013!
118
    last_r -= translation();
×
119
    r -= translation();
×
120
  }
121

122
  if (estimator != TallyEstimator::TRACKLENGTH) {
7,834,013!
123
    int32_t index_element = model::meshes[mesh_]->get_bin(r);
×
124
    if (index_element >= 0) {
×
125
      auto search = map_.find({index_element, p.material()});
×
126
      if (search != map_.end()) {
×
127
        match.bins_.push_back(search->second);
×
128
        match.weights_.push_back(1.0);
×
129
      }
130
    }
131
  } else {
132
    // First determine which elements the particle crosses (may or may not
133
    // actually match bins so we have to adjust bins_/weight_ after)
134
    int32_t n_start = match.bins_.size();
7,834,013✔
135
    model::meshes[mesh_]->bins_crossed(
7,834,013✔
136
      last_r, r, u, match.bins_, match.weights_);
7,834,013✔
137
    int32_t n_end = match.bins_.size();
7,834,013✔
138

139
    // Go through bins and weights and check which ones are actually a match
140
    // based on the (element, material) pair. For matches, overwrite the bin.
141
    int i = 0;
7,834,013✔
142
    for (int j = n_start; j < n_end; ++j) {
11,072,534✔
143
      int32_t index_element = match.bins_[j];
3,238,521✔
144
      double weight = match.weights_[j];
3,238,521✔
145
      auto search = map_.find({index_element, p.material()});
3,238,521✔
146
      if (search != map_.end()) {
3,238,521!
147
        match.bins_[n_start + i] = search->second;
3,238,521✔
148
        match.weights_[n_start + i] = weight;
3,238,521✔
149
        ++i;
3,238,521✔
150
      }
151
    }
152

153
    // Resize the vectors to remove the unmatched bins
154
    match.bins_.resize(n_start + i);
7,834,013✔
155
  }
156
}
157

158
void MeshMaterialFilter::to_statepoint(hid_t filter_group) const
22✔
159
{
160
  Filter::to_statepoint(filter_group);
22✔
161
  write_dataset(filter_group, "mesh", model::meshes[mesh_]->id_);
22✔
162

163
  size_t n = bins_.size();
22✔
164
  xt::xtensor<size_t, 2> data({n, 2});
22✔
165
  for (int64_t i = 0; i < n; ++i) {
132✔
166
    const auto& x = bins_[i];
110✔
167
    data(i, 0) = x.index_element;
110✔
168
    data(i, 1) = model::materials[x.index_mat]->id_;
110✔
169
  }
170
  write_dataset(filter_group, "bins", data);
22✔
171

172
  if (translated_) {
22!
173
    write_dataset(filter_group, "translation", translation_);
×
174
  }
175
}
22✔
176

177
std::string MeshMaterialFilter::text_label(int bin) const
132✔
178
{
179
  auto& x = bins_[bin];
132✔
180
  auto& mesh = *model::meshes.at(mesh_);
132✔
181
  return fmt::format("Mesh {}, {}, Material {}", mesh.id(),
132✔
182
    mesh.bin_label(x.index_element), model::materials[x.index_mat]->id_);
264✔
183
}
184

185
} // namespace openmc
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