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

openmc-dev / openmc / 14260484407

04 Apr 2025 07:41AM UTC coverage: 84.589% (-0.3%) from 84.851%
14260484407

Pull #3279

github

web-flow
Merge 33e03305e into 07f533461
Pull Request #3279: Hexagonal mesh model

2 of 332 new or added lines in 3 files covered. (0.6%)

2798 existing lines in 84 files now uncovered.

51799 of 61236 relevant lines covered (84.59%)

38650400.15 hits per line

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

45.54
/src/tallies/filter_sph_harm.cpp
1
#include "openmc/tallies/filter_sph_harm.h"
2

3
#include <cassert>
4
#include <utility> // For pair
5

6
#include <fmt/core.h>
7

8
#include "openmc/capi.h"
9
#include "openmc/error.h"
10
#include "openmc/math_functions.h"
11
#include "openmc/xml_interface.h"
12

13
namespace openmc {
14

15
void SphericalHarmonicsFilter::from_xml(pugi::xml_node node)
38✔
16
{
17
  this->set_order(std::stoi(get_node_value(node, "order")));
38✔
18
  if (check_for_node(node, "cosine")) {
38✔
19
    this->set_cosine(get_node_value(node, "cosine", true));
38✔
20
  }
21
}
38✔
22

23
void SphericalHarmonicsFilter::set_order(int order)
38✔
24
{
25
  if (order < 0) {
38✔
26
    throw std::invalid_argument {
×
27
      "Spherical harmonics order must be non-negative."};
×
28
  } else if (order > 10) {
38✔
UNCOV
29
    throw std::invalid_argument {"Spherical harmonics orders greater than 10 "
×
UNCOV
30
                                 "are currently not supported!"};
×
31
  }
32
  order_ = order;
38✔
33
  n_bins_ = (order_ + 1) * (order_ + 1);
38✔
34
}
38✔
35

36
void SphericalHarmonicsFilter::set_cosine(const std::string& cosine)
38✔
37
{
38
  if (cosine == "scatter") {
38✔
39
    cosine_ = SphericalHarmonicsCosine::scatter;
11✔
40
  } else if (cosine == "particle") {
27✔
41
    cosine_ = SphericalHarmonicsCosine::particle;
27✔
42
  } else {
UNCOV
43
    throw std::invalid_argument {fmt::format("Unrecognized cosine type, \"{}\" "
×
44
                                             "in spherical harmonics filter",
UNCOV
45
      cosine)};
×
46
  }
47
}
38✔
48

49
void SphericalHarmonicsFilter::get_all_bins(
4,586,692✔
50
  const Particle& p, TallyEstimator estimator, FilterMatch& match) const
51
{
52
  // Determine cosine term for scatter expansion if necessary
53
  vector<double> wgt(order_ + 1);
4,586,692✔
54
  if (cosine_ == SphericalHarmonicsCosine::scatter) {
4,586,692✔
55
    calc_pn_c(order_, p.mu(), wgt.data());
1,463✔
56
  } else {
57
    for (int i = 0; i < order_ + 1; i++) {
27,512,837✔
58
      wgt[i] = 1;
22,927,608✔
59
    }
60
  }
61

62
  // Find the Rn,m values
63
  vector<double> rn(n_bins_);
4,586,692✔
64
  calc_rn(order_, p.u_last(), rn.data());
4,586,692✔
65

66
  int j = 0;
4,586,692✔
67
  for (int n = 0; n < order_ + 1; n++) {
27,523,078✔
68
    // Calculate n-th order spherical harmonics for (u,v,w)
69
    int num_nm = 2 * n + 1;
22,936,386✔
70

71
    // Append the matching (bin,weight) for each moment
72
    for (int i = 0; i < num_nm; i++) {
137,635,872✔
73
      match.weights_.push_back(wgt[n] * rn[j]);
114,699,486✔
74
      match.bins_.push_back(j);
114,699,486✔
75
      ++j;
114,699,486✔
76
    }
77
  }
78
}
4,586,692✔
79

80
void SphericalHarmonicsFilter::to_statepoint(hid_t filter_group) const
33✔
81
{
82
  Filter::to_statepoint(filter_group);
33✔
83
  write_dataset(filter_group, "order", order_);
33✔
84
  if (cosine_ == SphericalHarmonicsCosine::scatter) {
33✔
85
    write_dataset(filter_group, "cosine", "scatter");
11✔
86
  } else {
87
    write_dataset(filter_group, "cosine", "particle");
22✔
88
  }
89
}
33✔
90

91
std::string SphericalHarmonicsFilter::text_label(int bin) const
1,617✔
92
{
93
  assert(bin >= 0 && bin < n_bins_);
1,323✔
94
  for (int n = 0; n < order_ + 1; n++) {
6,677✔
95
    if (bin < (n + 1) * (n + 1)) {
6,677✔
96
      int m = (bin - n * n) - n;
1,617✔
97
      return fmt::format("Spherical harmonic expansion, Y{},{}", n, m);
1,617✔
98
    }
99
  }
UNCOV
100
  UNREACHABLE();
×
101
}
102

103
//==============================================================================
104
// C-API functions
105
//==============================================================================
106

107
std::pair<int, SphericalHarmonicsFilter*> check_sphharm_filter(int32_t index)
×
108
{
109
  // Make sure this is a valid index to an allocated filter.
UNCOV
110
  int err = verify_filter(index);
×
UNCOV
111
  if (err) {
×
UNCOV
112
    return {err, nullptr};
×
113
  }
114

115
  // Get a pointer to the filter and downcast.
UNCOV
116
  const auto& filt_base = model::tally_filters[index].get();
×
117
  auto* filt = dynamic_cast<SphericalHarmonicsFilter*>(filt_base);
×
118

119
  // Check the filter type.
UNCOV
120
  if (!filt) {
×
121
    set_errmsg("Not a spherical harmonics filter.");
×
UNCOV
122
    err = OPENMC_E_INVALID_TYPE;
×
123
  }
124
  return {err, filt};
×
125
}
126

127
extern "C" int openmc_sphharm_filter_get_order(int32_t index, int* order)
×
128
{
129
  // Check the filter.
130
  auto check_result = check_sphharm_filter(index);
×
131
  auto err = check_result.first;
×
UNCOV
132
  auto filt = check_result.second;
×
UNCOV
133
  if (err)
×
134
    return err;
×
135

136
  // Output the order.
UNCOV
137
  *order = filt->order();
×
138
  return 0;
×
139
}
140

141
extern "C" int openmc_sphharm_filter_get_cosine(int32_t index, char cosine[])
×
142
{
143
  // Check the filter.
144
  auto check_result = check_sphharm_filter(index);
×
145
  auto err = check_result.first;
×
UNCOV
146
  auto filt = check_result.second;
×
UNCOV
147
  if (err)
×
148
    return err;
×
149

150
  // Output the cosine.
151
  if (filt->cosine() == SphericalHarmonicsCosine::scatter) {
×
UNCOV
152
    strcpy(cosine, "scatter");
×
153
  } else {
UNCOV
154
    strcpy(cosine, "particle");
×
155
  }
156
  return 0;
×
157
}
158

159
extern "C" int openmc_sphharm_filter_set_order(int32_t index, int order)
×
160
{
161
  // Check the filter.
162
  auto check_result = check_sphharm_filter(index);
×
163
  auto err = check_result.first;
×
UNCOV
164
  auto filt = check_result.second;
×
UNCOV
165
  if (err)
×
166
    return err;
×
167

168
  // Update the filter.
UNCOV
169
  filt->set_order(order);
×
170
  return 0;
×
171
}
172

UNCOV
173
extern "C" int openmc_sphharm_filter_set_cosine(
×
174
  int32_t index, const char cosine[])
175
{
176
  // Check the filter.
177
  auto check_result = check_sphharm_filter(index);
×
178
  auto err = check_result.first;
×
UNCOV
179
  auto filt = check_result.second;
×
UNCOV
180
  if (err)
×
UNCOV
181
    return err;
×
182

183
  // Update the filter.
184
  try {
185
    filt->set_cosine(cosine);
×
186
  } catch (const std::invalid_argument& e) {
×
187
    set_errmsg(e.what());
×
UNCOV
188
    return OPENMC_E_INVALID_ARGUMENT;
×
UNCOV
189
  }
×
UNCOV
190
  return 0;
×
191
}
192

193
} // 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