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

openmc-dev / openmc / 13423224479

19 Feb 2025 10:04PM UTC coverage: 85.021% (-0.007%) from 85.028%
13423224479

Pull #3225

github

web-flow
Merge 1c42b958f into bcc2a4c5f
Pull Request #3225: remove gsl-lite dependency

96 of 105 new or added lines in 38 files covered. (91.43%)

9 existing lines in 1 file now uncovered.

50630 of 59550 relevant lines covered (85.02%)

35314988.81 hits per line

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

45.92
/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)
41✔
16
{
17
  this->set_order(std::stoi(get_node_value(node, "order")));
41✔
18
  if (check_for_node(node, "cosine")) {
41✔
19
    this->set_cosine(get_node_value(node, "cosine", true));
41✔
20
  }
21
}
41✔
22

23
void SphericalHarmonicsFilter::set_order(int order)
41✔
24
{
25
  if (order < 0) {
41✔
26
    throw std::invalid_argument {
×
27
      "Spherical harmonics order must be non-negative."};
×
28
  }
29
  order_ = order;
41✔
30
  n_bins_ = (order_ + 1) * (order_ + 1);
41✔
31
}
41✔
32

33
void SphericalHarmonicsFilter::set_cosine(const std::string& cosine)
41✔
34
{
35
  if (cosine == "scatter") {
41✔
36
    cosine_ = SphericalHarmonicsCosine::scatter;
12✔
37
  } else if (cosine == "particle") {
29✔
38
    cosine_ = SphericalHarmonicsCosine::particle;
29✔
39
  } else {
40
    throw std::invalid_argument {fmt::format("Unrecognized cosine type, \"{}\" "
×
41
                                             "in spherical harmonics filter",
NEW
42
      cosine)};
×
43
  }
44
}
41✔
45

46
void SphericalHarmonicsFilter::get_all_bins(
5,003,664✔
47
  const Particle& p, TallyEstimator estimator, FilterMatch& match) const
48
{
49
  // Determine cosine term for scatter expansion if necessary
50
  vector<double> wgt(order_ + 1);
5,003,664✔
51
  if (cosine_ == SphericalHarmonicsCosine::scatter) {
5,003,664✔
52
    calc_pn_c(order_, p.mu(), wgt.data());
1,596✔
53
  } else {
54
    for (int i = 0; i < order_ + 1; i++) {
30,014,004✔
55
      wgt[i] = 1;
25,011,936✔
56
    }
57
  }
58

59
  // Find the Rn,m values
60
  vector<double> rn(n_bins_);
5,003,664✔
61
  calc_rn(order_, p.u_last(), rn.data());
5,003,664✔
62

63
  int j = 0;
5,003,664✔
64
  for (int n = 0; n < order_ + 1; n++) {
30,025,176✔
65
    // Calculate n-th order spherical harmonics for (u,v,w)
66
    int num_nm = 2 * n + 1;
25,021,512✔
67

68
    // Append the matching (bin,weight) for each moment
69
    for (int i = 0; i < num_nm; i++) {
150,148,224✔
70
      match.weights_.push_back(wgt[n] * rn[j]);
125,126,712✔
71
      match.bins_.push_back(j);
125,126,712✔
72
      ++j;
125,126,712✔
73
    }
74
  }
75
}
5,003,664✔
76

77
void SphericalHarmonicsFilter::to_statepoint(hid_t filter_group) const
36✔
78
{
79
  Filter::to_statepoint(filter_group);
36✔
80
  write_dataset(filter_group, "order", order_);
36✔
81
  if (cosine_ == SphericalHarmonicsCosine::scatter) {
36✔
82
    write_dataset(filter_group, "cosine", "scatter");
12✔
83
  } else {
84
    write_dataset(filter_group, "cosine", "particle");
24✔
85
  }
86
}
36✔
87

88
std::string SphericalHarmonicsFilter::text_label(int bin) const
1,764✔
89
{
90
  assert(bin >= 0 && bin < n_bins_);
1,470✔
91
  for (int n = 0; n < order_ + 1; n++) {
7,284✔
92
    if (bin < (n + 1) * (n + 1)) {
7,284✔
93
      int m = (bin - n * n) - n;
1,764✔
94
      return fmt::format("Spherical harmonic expansion, Y{},{}", n, m);
1,764✔
95
    }
96
  }
97
  UNREACHABLE();
×
98
}
99

100
//==============================================================================
101
// C-API functions
102
//==============================================================================
103

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

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

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

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

133
  // Output the order.
134
  *order = filt->order();
×
135
  return 0;
×
136
}
137

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

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

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

165
  // Update the filter.
166
  filt->set_order(order);
×
167
  return 0;
×
168
}
169

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

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

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