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

openmc-dev / openmc / 19802228956

30 Nov 2025 05:13PM UTC coverage: 82.033% (-0.04%) from 82.068%
19802228956

Pull #3659

github

web-flow
Merge d855c5c73 into ef22558f4
Pull Request #3659: Delayed neutron fraction by isotope with IFP method

16956 of 23539 branches covered (72.03%)

Branch coverage included in aggregate %.

65 of 83 new or added lines in 10 files covered. (78.31%)

24 existing lines in 2 files now uncovered.

54921 of 64081 relevant lines covered (85.71%)

42139860.32 hits per line

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

83.5
/src/ifp.cpp
1
#include "openmc/ifp.h"
2

3
#include "openmc/bank.h"
4
#include "openmc/message_passing.h"
5
#include "openmc/particle.h"
6
#include "openmc/particle_data.h"
7
#include "openmc/settings.h"
8
#include "openmc/simulation.h"
9
#include "openmc/vector.h"
10

11
namespace openmc {
12

13
bool is_beta_effective_or_both()
6,002,152✔
14
{
15
  if (settings::ifp_parameter == IFPParameter::BetaEffective ||
6,002,152!
16
      settings::ifp_parameter == IFPParameter::Both) {
6,002,152!
17
    return true;
6,002,152✔
18
  }
19
  return false;
×
20
}
21

22
bool is_generation_time_or_both()
5,020,528✔
23
{
24
  if (settings::ifp_parameter == IFPParameter::GenerationTime ||
5,020,528!
25
      settings::ifp_parameter == IFPParameter::Both) {
5,020,528!
26
    return true;
5,020,528✔
27
  }
28
  return false;
×
29
}
30

31
void ifp(const Particle& p, int64_t idx)
1,352,626✔
32
{
33
  if (is_beta_effective_or_both()) {
1,352,626!
34
    if (settings::ifp_beta_nuclide == true) {
1,352,626!
35
      const auto& delayed_groups =
NEW
36
        simulation::ifp_source_delayed_group_bank[p.current_work() - 1];
×
NEW
37
      simulation::ifp_fission_delayed_group_bank[idx] =
×
NEW
38
        _ifp(p.delayed_group(), delayed_groups);
×
39
      const auto& ancestor_nuclides =
NEW
40
        simulation::ifp_source_ancestor_nuclide_bank[p.current_work() - 1];
×
NEW
41
      simulation::ifp_fission_ancestor_nuclide_bank[idx] =
×
NEW
42
        _ifp(p.event_nuclide(), ancestor_nuclides);
×
43
    } else {
44
      const auto& delayed_groups =
45
        simulation::ifp_source_delayed_group_bank[p.current_work() - 1];
1,352,626✔
46
      simulation::ifp_fission_delayed_group_bank[idx] =
1,352,626✔
47
        _ifp(p.delayed_group(), delayed_groups);
2,705,252✔
48
    }
49
  }
50
  if (is_generation_time_or_both()) {
1,352,626!
51
    const auto& lifetimes =
52
      simulation::ifp_source_lifetime_bank[p.current_work() - 1];
1,352,626✔
53
    simulation::ifp_fission_lifetime_bank[idx] = _ifp(p.lifetime(), lifetimes);
1,352,626✔
54
  }
55
}
1,352,626✔
56

57
void resize_simulation_ifp_banks()
76✔
58
{
59
  resize_ifp_data(simulation::ifp_source_delayed_group_bank,
76✔
60
    simulation::ifp_source_ancestor_nuclide_bank,
61
    simulation::ifp_source_lifetime_bank, simulation::work_per_rank);
62
  resize_ifp_data(simulation::ifp_fission_delayed_group_bank,
76✔
63
    simulation::ifp_fission_ancestor_nuclide_bank,
64
    simulation::ifp_fission_lifetime_bank, 3 * simulation::work_per_rank);
65
}
76✔
66

67
void copy_ifp_data_from_fission_banks(int i_bank, vector<int>& delayed_groups,
2,672,626✔
68
  vector<int>& ancestors, vector<double>& lifetimes)
69
{
70
  if (is_beta_effective_or_both()) {
2,672,626!
71
    delayed_groups = simulation::ifp_fission_delayed_group_bank[i_bank];
2,672,626✔
72
    ancestors = simulation::ifp_fission_ancestor_nuclide_bank[i_bank];
2,672,626✔
73
  }
74
  if (is_generation_time_or_both()) {
2,672,626!
75
    lifetimes = simulation::ifp_fission_lifetime_bank[i_bank];
2,672,626✔
76
  }
77
}
2,672,626✔
78

79
#ifdef OPENMC_MPI
80

81
void broadcast_ifp_n_generation(int& n_generation,
800✔
82
  const vector<vector<int>>& delayed_groups,
83
  const vector<vector<int>>& ancestors, const vector<vector<double>>& lifetimes)
84
{
85
  if (mpi::rank == 0) {
800✔
86
    if (is_beta_effective_or_both()) {
600!
87
      n_generation = static_cast<int>(delayed_groups[0].size());
600✔
88
    } else {
89
      n_generation = static_cast<int>(lifetimes[0].size());
90
    }
91
  }
92
  MPI_Bcast(&n_generation, 1, MPI_INT, 0, mpi::intracomm);
800✔
93
}
800✔
94

95
void send_ifp_info(int64_t idx, int64_t n, int n_generation, int neighbor,
200✔
96
  vector<MPI_Request>& requests, const vector<vector<int>>& delayed_groups,
97
  vector<int>& send_delayed_groups, const vector<vector<int>>& ancestors,
98
  vector<int>& send_ancestors, const vector<vector<double>>& lifetimes,
99
  vector<double>& send_lifetimes)
100
{
101
  // Copy data in send buffers
102
  for (int i = idx; i < idx + n; i++) {
3,610✔
103
    if (is_beta_effective_or_both()) {
3,410!
104
      std::copy(delayed_groups[i].begin(), delayed_groups[i].end(),
3,410✔
105
        send_delayed_groups.begin() + i * n_generation);
3,410✔
106
      std::copy(ancestors[i].begin(), ancestors[i].end(),
3,410✔
107
        send_ancestors.begin() + i * n_generation);
6,820✔
108
    }
109
    if (is_generation_time_or_both()) {
3,410!
110
      std::copy(lifetimes[i].begin(), lifetimes[i].end(),
3,410✔
111
        send_lifetimes.begin() + i * n_generation);
6,820✔
112
    }
113
  }
114
  // Send delayed groups
115
  if (is_beta_effective_or_both()) {
200!
116
    requests.emplace_back();
200✔
117
    MPI_Isend(&send_delayed_groups[n_generation * idx],
200✔
118
      n_generation * static_cast<int>(n), MPI_INT, neighbor, mpi::rank,
119
      mpi::intracomm, &requests.back());
200✔
120
    // Is it needed also for the ancestor nuclide
121
    MPI_Isend(&send_ancestors[n_generation * idx],
200✔
122
      n_generation * static_cast<int>(n), MPI_INT, neighbor, mpi::rank,
123
      mpi::intracomm, &requests.back());
200✔
124
  }
125
  // Send lifetimes
126
  if (is_generation_time_or_both()) {
200!
127
    requests.emplace_back();
200✔
128
    MPI_Isend(&send_lifetimes[n_generation * idx],
200✔
129
      n_generation * static_cast<int>(n), MPI_DOUBLE, neighbor, mpi::rank,
130
      mpi::intracomm, &requests.back());
200✔
131
  }
132
}
200✔
133

134
void receive_ifp_data(int64_t idx, int64_t n, int n_generation, int neighbor,
200✔
135
  vector<MPI_Request>& requests, vector<int>& delayed_groups,
136
  vector<int>& ancestors, vector<double>& lifetimes,
137
  vector<DeserializationInfo>& deserialization)
138
{
139
  // Receive delayed groups
140
  if (is_beta_effective_or_both()) {
200!
141
    requests.emplace_back();
200✔
142
    MPI_Irecv(&delayed_groups[n_generation * idx],
200✔
143
      n_generation * static_cast<int>(n), MPI_INT, neighbor, neighbor,
144
      mpi::intracomm, &requests.back());
200✔
145
    // Is it needed also for the ancestor nuclide
146
    MPI_Irecv(&ancestors[n_generation * idx],
200✔
147
      n_generation * static_cast<int>(n), MPI_INT, neighbor, neighbor,
148
      mpi::intracomm, &requests.back());
200✔
149
  }
150
  // Receive lifetimes
151
  if (is_generation_time_or_both()) {
200!
152
    requests.emplace_back();
200✔
153
    MPI_Irecv(&lifetimes[n_generation * idx],
200✔
154
      n_generation * static_cast<int>(n), MPI_DOUBLE, neighbor, neighbor,
155
      mpi::intracomm, &requests.back());
200✔
156
  }
157
  // Deserialization info to reconstruct data later
158
  DeserializationInfo info = {idx, n};
200✔
159
  deserialization.push_back(info);
200✔
160
}
200✔
161

162
void copy_partial_ifp_data_to_source_banks(int64_t idx, int n, int64_t i_bank,
800✔
163
  const vector<vector<int>>& delayed_groups,
164
  const vector<vector<int>>& ancestors, const vector<vector<double>>& lifetimes)
165
{
166
  if (is_beta_effective_or_both()) {
800!
167
    std::copy(&delayed_groups[idx], &delayed_groups[idx + n],
800✔
168
      &simulation::ifp_source_delayed_group_bank[i_bank]);
800✔
169
    std::copy(&ancestors[idx], &ancestors[idx + n],
800✔
170
      &simulation::ifp_source_ancestor_nuclide_bank[i_bank]);
800✔
171
  }
172
  if (is_generation_time_or_both()) {
800!
173
    std::copy(&lifetimes[idx], &lifetimes[idx + n],
800✔
174
      &simulation::ifp_source_lifetime_bank[i_bank]);
800✔
175
  }
176
}
800✔
177

178
void deserialize_ifp_info(int n_generation,
800✔
179
  const vector<DeserializationInfo>& deserialization,
180
  const vector<int>& delayed_groups, const vector<int>& ancestors,
181
  const vector<double>& lifetimes)
182
{
183
  for (auto info : deserialization) {
1,000✔
184
    int64_t index_local = info.index_local;
200✔
185
    int64_t n = info.n;
200✔
186

187
    for (int i = index_local; i < index_local + n; i++) {
3,610✔
188
      if (is_beta_effective_or_both()) {
3,410!
189
        vector<int> delayed_groups_received(
190
          delayed_groups.begin() + n_generation * i,
191
          delayed_groups.begin() + n_generation * (i + 1));
3,410✔
192
        simulation::ifp_source_delayed_group_bank[i] = delayed_groups_received;
3,410✔
193
        vector<int> ancestors_received(ancestors.begin() + n_generation * i,
194
          ancestors.begin() + n_generation * (i + 1));
3,410✔
195
        simulation::ifp_source_ancestor_nuclide_bank[i] = ancestors_received;
3,410✔
196
      }
3,410✔
197
      if (is_generation_time_or_both()) {
3,410!
198
        vector<double> lifetimes_received(lifetimes.begin() + n_generation * i,
199
          lifetimes.begin() + n_generation * (i + 1));
3,410✔
200
        simulation::ifp_source_lifetime_bank[i] = lifetimes_received;
3,410✔
201
      }
3,410✔
202
    }
203
  }
204
}
800✔
205

206
#endif
207

208
void copy_complete_ifp_data_to_source_banks(
720✔
209
  const vector<vector<int>>& delayed_groups,
210
  const vector<vector<int>>& ancestors, const vector<vector<double>>& lifetimes)
211
{
212
  if (is_beta_effective_or_both()) {
720!
213
    std::copy(delayed_groups.data(),
1,440✔
214
      delayed_groups.data() + settings::n_particles,
720✔
215
      simulation::ifp_source_delayed_group_bank.begin());
216
    std::copy(ancestors.data(), ancestors.data() + settings::n_particles,
720✔
217
      simulation::ifp_source_ancestor_nuclide_bank.begin());
218
  }
219
  if (is_generation_time_or_both()) {
720!
220
    std::copy(lifetimes.data(), lifetimes.data() + settings::n_particles,
720✔
221
      simulation::ifp_source_lifetime_bank.begin());
222
  }
223
}
720✔
224

225
void allocate_temporary_vector_ifp(vector<vector<int>>& delayed_groups,
1,520✔
226
  vector<vector<int>>& ancestors, vector<vector<double>>& lifetimes)
227
{
228
  if (is_beta_effective_or_both()) {
1,520!
229
    delayed_groups.resize(simulation::fission_bank.size());
1,520✔
230
    ancestors.resize(simulation::fission_bank.size());
1,520✔
231
  }
232
  if (is_generation_time_or_both()) {
1,520!
233
    lifetimes.resize(simulation::fission_bank.size());
1,520✔
234
  }
235
}
1,520✔
236

237
void copy_ifp_data_to_fission_banks(const vector<int>* const delayed_groups_ptr,
1,520✔
238
  const vector<int>* const ancestors_ptr, const vector<double>* lifetimes_ptr)
239
{
240
  if (is_beta_effective_or_both()) {
1,520!
241
    std::copy(delayed_groups_ptr,
1,520✔
242
      delayed_groups_ptr + simulation::fission_bank.size(),
1,520✔
243
      simulation::ifp_fission_delayed_group_bank.data());
244
    std::copy(ancestors_ptr, ancestors_ptr + simulation::fission_bank.size(),
1,520✔
245
      simulation::ifp_fission_ancestor_nuclide_bank.data());
246
  }
247
  if (is_generation_time_or_both()) {
1,520!
248
    std::copy(lifetimes_ptr, lifetimes_ptr + simulation::fission_bank.size(),
1,520✔
249
      simulation::ifp_fission_lifetime_bank.data());
250
  }
251
}
1,520✔
252

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

© 2025 Coveralls, Inc