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

openmc-dev / openmc / 14645405719

24 Apr 2025 03:23PM UTC coverage: 84.416% (-0.4%) from 84.851%
14645405719

Pull #3279

github

web-flow
Merge 8a3e52b5d into 820648dae
Pull Request #3279: Hexagonal mesh model

94 of 475 new or added lines in 5 files covered. (19.79%)

3299 existing lines in 93 files now uncovered.

52250 of 61896 relevant lines covered (84.42%)

36990428.73 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)
16,000✔
36
{
37
  SourceSite site;
16,000✔
38

39
  switch (particle->pdgcode) {
16,000✔
40
  case 2112:
16,000✔
41
    site.particle = ParticleType::neutron;
16,000✔
42
    break;
16,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];
16,000✔
56
  site.r.y = particle->position[1];
16,000✔
57
  site.r.z = particle->position[2];
16,000✔
58
  site.u.x = particle->direction[0];
16,000✔
59
  site.u.y = particle->direction[1];
16,000✔
60
  site.u.z = particle->direction[2];
16,000✔
61

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

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

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

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

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

82
  for (int i = 0; i < n_sites; i++) {
16,016✔
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;
16,000✔
87
    while (pdg != 2112 && pdg != 22 && pdg != 11 && pdg != -11) {
32,000✔
88
      particle = mcpl_read(mcpl_file);
16,000✔
89
      pdg = particle->pdgcode;
16,000✔
90
    }
91

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

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

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

108
  return sites;
32✔
109
}
×
110

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

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

120
  if (mpi::master) {
16✔
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) {
27✔
130
      // number of particles for node node i
131
      size_t count[] {static_cast<size_t>(bank_index[i + 1] - bank_index[i])};
16✔
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) {
11,016✔
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;
11,000✔
144
        p.position[1] = site.r.y;
11,000✔
145
        p.position[2] = site.r.z;
11,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;
11,000✔
150
        p.direction[1] = site.u.y;
11,000✔
151
        p.direction[2] = site.u.z;
11,000✔
152

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

158
        switch (site.particle) {
11,000✔
159
        case ParticleType::neutron:
11,000✔
160
          p.pdgcode = 2112;
11,000✔
161
          break;
11,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);
11,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
}
16✔
187
#endif
188

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

191
void write_mcpl_source_point(const char* filename, span<SourceSite> source_bank,
16✔
192
  const vector<int64_t>& bank_index)
193
{
194
  std::string filename_(filename);
16✔
195
  const auto extension = get_file_extension(filename_);
16✔
196
  if (extension == "") {
16✔
UNCOV
197
    filename_.append(".mcpl");
×
198
  } else if (extension != "mcpl") {
16✔
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;
16✔
207
  if (mpi::master) {
16✔
208
    file_id = mcpl_create_outfile(filename_.c_str());
11✔
209
    if (VERSION_DEV) {
210
      line = fmt::format("OpenMC {0}.{1}.{2}-dev{3}", VERSION_MAJOR,
20✔
211
        VERSION_MINOR, VERSION_RELEASE, VERSION_COMMIT_COUNT);
11✔
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());
11✔
217
  }
218

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

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

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