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

openmc-dev / openmc / 13003369302

28 Jan 2025 04:02AM UTC coverage: 84.852% (+0.001%) from 84.851%
13003369302

Pull #3042

github

web-flow
Merge 60e348600 into 2bea7f338
Pull Request #3042: Rely on std::filesystem for file_utils

26 of 29 new or added lines in 5 files covered. (89.66%)

3 existing lines in 3 files now uncovered.

50100 of 59044 relevant lines covered (84.85%)

34845854.57 hits per line

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

76.6
/src/mcpl_interface.cpp
1
#include "openmc/mcpl_interface.h"
2

3
#include "openmc/bank.h"
4
#include "openmc/error.h"
5
#include "openmc/file_utils.h"
6
#include "openmc/message_passing.h"
7
#include "openmc/settings.h"
8
#include "openmc/simulation.h"
9
#include "openmc/state_point.h"
10
#include "openmc/vector.h"
11

12
#include <fmt/core.h>
13

14
#ifdef OPENMC_MCPL
15
#include <mcpl.h>
16
#endif
17

18
namespace openmc {
19

20
//==============================================================================
21
// Constants
22
//==============================================================================
23

24
#ifdef OPENMC_MCPL
25
const bool MCPL_ENABLED = true;
26
#else
27
const bool MCPL_ENABLED = false;
28
#endif
29

30
//==============================================================================
31
// Functions
32
//==============================================================================
33

34
#ifdef OPENMC_MCPL
35
SourceSite mcpl_particle_to_site(const mcpl_particle_t* particle)
17,000 ✔
36
{
37
  SourceSite site;
17,000 ✔
38

39
  switch (particle->pdgcode) {
17,000 ✔
40
  case 2112:
17,000 ✔
41
    site.particle = ParticleType::neutron;
17,000 ✔
42
    break;
17,000 ✔
43
  case 22:
×
44
    site.particle = ParticleType::photon;
×
45
    break;
×
46
  case 11:
×
47
    site.particle = ParticleType::electron;
×
48
    break;
×
49
  case -11:
×
50
    site.particle = ParticleType::positron;
×
51
    break;
×
52
  }
53

54
  // Copy position and direction
55
  site.r.x = particle->position[0];
17,000 ✔
56
  site.r.y = particle->position[1];
17,000 ✔
57
  site.r.z = particle->position[2];
17,000 ✔
58
  site.u.x = particle->direction[0];
17,000 ✔
59
  site.u.y = particle->direction[1];
17,000 ✔
60
  site.u.z = particle->direction[2];
17,000 ✔
61

62
  // MCPL stores kinetic energy in [MeV], time in [ms]
63
  site.E = particle->ekin * 1e6;
17,000 ✔
64
  site.time = particle->time * 1e-3;
17,000 ✔
65
  site.wgt = particle->weight;
17,000 ✔
66

67
  return site;
17,000 ✔
68
}
69
#endif
70

71
//==============================================================================
72

73
vector<SourceSite> mcpl_source_sites(std::string path)
17 ✔
74
{
75
  vector<SourceSite> sites;
17 ✔
76

77
#ifdef OPENMC_MCPL
78
  // Open MCPL file and determine number of particles
79
  auto mcpl_file = mcpl_open_file(path.c_str());
17 ✔
80
  size_t n_sites = mcpl_hdr_nparticles(mcpl_file);
17 ✔
81

82
  for (int i = 0; i < n_sites; i++) {
17,017 ✔
83
    // Extract particle from mcpl-file, checking if it is a neutron, photon,
84
    // electron, or positron. Otherwise skip.
85
    const mcpl_particle_t* particle;
86
    int pdg = 0;
17,000 ✔
87
    while (pdg != 2112 && pdg != 22 && pdg != 11 && pdg != -11) {
34,000 ✔
88
      particle = mcpl_read(mcpl_file);
17,000 ✔
89
      pdg = particle->pdgcode;
17,000 ✔
90
    }
91

92
    // Convert to source site and add to vector
93
    sites.push_back(mcpl_particle_to_site(particle));
17,000 ✔
94
  }
95

96
  // Check that some sites were read
97
  if (sites.empty()) {
17 ✔
98
    fatal_error("MCPL file contained no neutron, photon, electron, or positron "
×
99
                "source particles.");
100
  }
101

102
  mcpl_close_file(mcpl_file);
17 ✔
103
#else
104
  fatal_error(
105
    "Your build of OpenMC does not support reading MCPL source files.");
106
#endif
107

108
  return sites;
34 ✔
109
}
×
110

111
//==============================================================================
112

113
#ifdef OPENMC_MCPL
114
void write_mcpl_source_bank(mcpl_outfile_t file_id,
17 ✔
115
  gsl::span<SourceSite> source_bank, const vector<int64_t>& bank_index)
116
{
117
  int64_t dims_size = settings::n_particles;
17 ✔
118
  int64_t count_size = simulation::work_per_rank;
17 ✔
119

120
  if (mpi::master) {
17 ✔
121
    // Particles are writeen to disk from the master node only
122

123
    // Save source bank sites since the array is overwritten below
124
#ifdef OPENMC_MPI
125
    vector<SourceSite> temp_source {source_bank.begin(), source_bank.end()};
5 ✔
126
#endif
127

128
    // loop over the other nodes and receive data - then write those.
129
    for (int i = 0; i < mpi::n_procs; ++i) {
29 ✔
130
      // number of particles for node node i
131
      size_t count[] {static_cast<size_t>(bank_index[i + 1] - bank_index[i])};
17 ✔
132

133
#ifdef OPENMC_MPI
134
      if (i > 0)
10 ✔
135
        MPI_Recv(source_bank.data(), count[0], mpi::source_site, i, i,
5 ✔
136
          mpi::intracomm, MPI_STATUS_IGNORE);
137
#endif
138
      // now write the source_bank data again.
139
      for (const auto& site : source_bank) {
12,017 ✔
140
        // particle is now at the iterator
141
        // write it to the mcpl-file
142
        mcpl_particle_t p;
143
        p.position[0] = site.r.x;
12,000 ✔
144
        p.position[1] = site.r.y;
12,000 ✔
145
        p.position[2] = site.r.z;
12,000 ✔
146

147
        // mcpl requires that the direction vector is unit length
148
        // which is also the case in openmc
149
        p.direction[0] = site.u.x;
12,000 ✔
150
        p.direction[1] = site.u.y;
12,000 ✔
151
        p.direction[2] = site.u.z;
12,000 ✔
152

153
        // MCPL stores kinetic energy in [MeV], time in [ms]
154
        p.ekin = site.E * 1e-6;
12,000 ✔
155
        p.time = site.time * 1e3;
12,000 ✔
156
        p.weight = site.wgt;
12,000 ✔
157

158
        switch (site.particle) {
12,000 ✔
159
        case ParticleType::neutron:
12,000 ✔
160
          p.pdgcode = 2112;
12,000 ✔
161
          break;
12,000 ✔
162
        case ParticleType::photon:
×
163
          p.pdgcode = 22;
×
164
          break;
×
165
        case ParticleType::electron:
×
166
          p.pdgcode = 11;
×
167
          break;
×
168
        case ParticleType::positron:
×
169
          p.pdgcode = -11;
×
170
          break;
×
171
        }
172

173
        mcpl_add_particle(file_id, &p);
12,000 ✔
174
      }
175
    }
176
#ifdef OPENMC_MPI
177
    // Restore state of source bank
178
    std::copy(temp_source.begin(), temp_source.end(), source_bank.begin());
5 ✔
179
#endif
180
  } else {
5 ✔
181
#ifdef OPENMC_MPI
182
    MPI_Send(source_bank.data(), count_size, mpi::source_site, 0, mpi::rank,
5 ✔
183
      mpi::intracomm);
184
#endif
185
  }
186
}
17 ✔
187
#endif
188

189
//==============================================================================
190

191
void write_mcpl_source_point(const char* filename,
17 ✔
192
  gsl::span<SourceSite> source_bank, const vector<int64_t>& bank_index)
193
{
194
  std::string filename_(filename);
17 ✔
195
  const auto extension = get_file_extension(filename_);
17 ✔
196
  if (extension == "") {
17 ✔
UNCOV
197
    filename_.append(".mcpl");
×
198
  } else if (extension != "mcpl") {
17 ✔
199
    warning("write_mcpl_source_point was passed a file extension differing "
×
200
            "from .mcpl, but an mcpl file will be written.");
201
  }
202

203
#ifdef OPENMC_MCPL
204
  mcpl_outfile_t file_id;
205

206
  std::string line;
17 ✔
207
  if (mpi::master) {
17 ✔
208
    file_id = mcpl_create_outfile(filename_.c_str());
12 ✔
209
    if (VERSION_DEV) {
210
      line = fmt::format("OpenMC {0}.{1}.{2}-development", VERSION_MAJOR,
22 ✔
211
        VERSION_MINOR, VERSION_RELEASE);
12 ✔
212
    } else {
213
      line = fmt::format(
214
        "OpenMC {0}.{1}.{2}", VERSION_MAJOR, VERSION_MINOR, VERSION_RELEASE);
215
    }
216
    mcpl_hdr_set_srcname(file_id, line.c_str());
12 ✔
217
  }
218

219
  write_mcpl_source_bank(file_id, source_bank, bank_index);
17 ✔
220

221
  if (mpi::master) {
17 ✔
222
    mcpl_close_outfile(file_id);
12 ✔
223
  }
224
#endif
225
}
17 ✔
226

227
} // namespace openmc
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc