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

openmc-dev / openmc / 15371300071

01 Jun 2025 05:04AM UTC coverage: 85.143% (+0.3%) from 84.827%
15371300071

Pull #3176

github

web-flow
Merge 4f739184a into cb95c784b
Pull Request #3176: MeshFilter rotation - solution to issue #3166

86 of 99 new or added lines in 4 files covered. (86.87%)

3707 existing lines in 117 files now uncovered.

52212 of 61323 relevant lines covered (85.14%)

42831974.38 hits per line

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

76.47
/src/bank.cpp
1
#include "openmc/bank.h"
2
#include "openmc/capi.h"
3
#include "openmc/error.h"
4
#include "openmc/ifp.h"
5
#include "openmc/message_passing.h"
6
#include "openmc/simulation.h"
7
#include "openmc/vector.h"
8

9
#include <cstdint>
10

11
namespace openmc {
12

13
//==============================================================================
14
// Global variables
15
//==============================================================================
16

17
namespace simulation {
18

19
vector<SourceSite> source_bank;
20

21
SharedArray<SourceSite> surf_source_bank;
22

23
// The fission bank is allocated as a SharedArray, rather than a vector, as it
24
// will be shared by all threads in the simulation. It will be allocated to a
25
// fixed maximum capacity in the init_fission_bank() function. Then, Elements
26
// will be added to it by using SharedArray's special thread_safe_append()
27
// function.
28
SharedArray<SourceSite> fission_bank;
29

30
vector<vector<int>> ifp_source_delayed_group_bank;
31

32
vector<vector<double>> ifp_source_lifetime_bank;
33

34
vector<vector<int>> ifp_fission_delayed_group_bank;
35

36
vector<vector<double>> ifp_fission_lifetime_bank;
37

38
// Each entry in this vector corresponds to the number of progeny produced
39
// this generation for the particle located at that index. This vector is
40
// used to efficiently sort the fission bank after each iteration.
41
vector<int64_t> progeny_per_particle;
42

43
} // namespace simulation
44

45
//==============================================================================
46
// Non-member functions
47
//==============================================================================
48

49
void free_memory_bank()
9,188✔
50
{
51
  simulation::source_bank.clear();
9,188✔
52
  simulation::surf_source_bank.clear();
9,188✔
53
  simulation::fission_bank.clear();
9,188✔
54
  simulation::progeny_per_particle.clear();
9,188✔
55
  simulation::ifp_source_delayed_group_bank.clear();
9,188✔
56
  simulation::ifp_source_lifetime_bank.clear();
9,188✔
57
  simulation::ifp_fission_delayed_group_bank.clear();
9,188✔
58
  simulation::ifp_fission_lifetime_bank.clear();
9,188✔
59
}
9,188✔
60

61
void init_fission_bank(int64_t max)
4,833✔
62
{
63
  simulation::fission_bank.reserve(max);
4,833✔
64
  simulation::progeny_per_particle.resize(simulation::work_per_rank);
4,833✔
65
}
4,833✔
66

67
// Performs an O(n) sort on the fission bank, by leveraging
68
// the parent_id and progeny_id fields of banked particles. See the following
69
// paper for more details:
70
// "Reproducibility and Monte Carlo Eigenvalue Calculations," F.B. Brown and
71
// T.M. Sutton, 1992 ANS Annual Meeting, Transactions of the American Nuclear
72
// Society, Volume 65, Page 235.
73
void sort_fission_bank()
104,450✔
74
{
75
  // Ensure we don't read off the end of the array if we ran with 0 particles
76
  if (simulation::progeny_per_particle.size() == 0) {
104,450✔
UNCOV
77
    return;
×
78
  }
79

80
  // Perform exclusive scan summation to determine starting indices in fission
81
  // bank for each parent particle id
82
  int64_t tmp = simulation::progeny_per_particle[0];
104,450✔
83
  simulation::progeny_per_particle[0] = 0;
104,450✔
84
  for (int64_t i = 1; i < simulation::progeny_per_particle.size(); i++) {
182,177,000✔
85
    int64_t value = simulation::progeny_per_particle[i - 1] + tmp;
182,072,550✔
86
    tmp = simulation::progeny_per_particle[i];
182,072,550✔
87
    simulation::progeny_per_particle[i] = value;
182,072,550✔
88
  }
89

90
  // TODO: C++17 introduces the exclusive_scan() function which could be
91
  // used to replace everything above this point in this function.
92

93
  // We need a scratch vector to make permutation of the fission bank into
94
  // sorted order easy. Under normal usage conditions, the fission bank is
95
  // over provisioned, so we can use that as scratch space.
96
  SourceSite* sorted_bank;
97
  vector<SourceSite> sorted_bank_holder;
104,450✔
98
  vector<vector<int>> sorted_ifp_delayed_group_bank;
104,450✔
99
  vector<vector<double>> sorted_ifp_lifetime_bank;
104,450✔
100

101
  // If there is not enough space, allocate a temporary vector and point to it
102
  if (simulation::fission_bank.size() >
104,450✔
103
      simulation::fission_bank.capacity() / 2) {
104,450✔
104
    sorted_bank_holder.resize(simulation::fission_bank.size());
1,131✔
105
    sorted_bank = sorted_bank_holder.data();
1,131✔
106
  } else { // otherwise, point sorted_bank to unused portion of the fission bank
107
    sorted_bank = &simulation::fission_bank[simulation::fission_bank.size()];
103,319✔
108
  }
109

110
  if (settings::ifp_on) {
104,450✔
111
    allocate_temporary_vector_ifp(
440✔
112
      sorted_ifp_delayed_group_bank, sorted_ifp_lifetime_bank);
113
  }
114

115
  // Use parent and progeny indices to sort fission bank
116
  for (int64_t i = 0; i < simulation::fission_bank.size(); i++) {
182,165,842✔
117
    const auto& site = simulation::fission_bank[i];
182,061,392✔
118
    int64_t offset = site.parent_id - 1 - simulation::work_index[mpi::rank];
182,061,392✔
119
    int64_t idx = simulation::progeny_per_particle[offset] + site.progeny_id;
182,061,392✔
120
    if (idx >= simulation::fission_bank.size()) {
182,061,392✔
UNCOV
121
      fatal_error("Mismatch detected between sum of all particle progeny and "
×
122
                  "shared fission bank size.");
123
    }
124
    sorted_bank[idx] = site;
182,061,392✔
125
    if (settings::ifp_on) {
182,061,392✔
126
      copy_ifp_data_from_fission_banks(
302,625✔
127
        i, sorted_ifp_delayed_group_bank[idx], sorted_ifp_lifetime_bank[idx]);
302,625✔
128
    }
129
  }
130

131
  // Copy sorted bank into the fission bank
132
  std::copy(sorted_bank, sorted_bank + simulation::fission_bank.size(),
104,450✔
133
    simulation::fission_bank.data());
134
  if (settings::ifp_on) {
104,450✔
135
    copy_ifp_data_to_fission_banks(
440✔
136
      sorted_ifp_delayed_group_bank.data(), sorted_ifp_lifetime_bank.data());
440✔
137
  }
138
}
104,450✔
139

140
//==============================================================================
141
// C API
142
//==============================================================================
143

144
extern "C" int openmc_source_bank(void** ptr, int64_t* n)
15✔
145
{
146
  if (!ptr || !n) {
15✔
UNCOV
147
    set_errmsg("Received null pointer.");
×
UNCOV
148
    return OPENMC_E_INVALID_ARGUMENT;
×
149
  }
150

151
  if (simulation::source_bank.size() == 0) {
15✔
UNCOV
152
    set_errmsg("Source bank has not been allocated.");
×
UNCOV
153
    return OPENMC_E_ALLOCATE;
×
154
  } else {
155
    *ptr = simulation::source_bank.data();
15✔
156
    *n = simulation::source_bank.size();
15✔
157
    return 0;
15✔
158
  }
159
}
160

UNCOV
161
extern "C" int openmc_fission_bank(void** ptr, int64_t* n)
×
162
{
UNCOV
163
  if (!ptr || !n) {
×
UNCOV
164
    set_errmsg("Received null pointer.");
×
UNCOV
165
    return OPENMC_E_INVALID_ARGUMENT;
×
166
  }
167

UNCOV
168
  if (simulation::fission_bank.size() == 0) {
×
UNCOV
169
    set_errmsg("Fission bank has not been allocated.");
×
UNCOV
170
    return OPENMC_E_ALLOCATE;
×
171
  } else {
UNCOV
172
    *ptr = simulation::fission_bank.data();
×
UNCOV
173
    *n = simulation::fission_bank.size();
×
UNCOV
174
    return 0;
×
175
  }
176
}
177

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