OpenMC/src/track_output.cpp

158 lines
4.9 KiB
C++

#include "openmc/track_output.h"
#include "openmc/constants.h"
#include "openmc/hdf5_interface.h"
#include "openmc/message_passing.h"
#include "openmc/position.h"
#include "openmc/settings.h"
#include "openmc/simulation.h"
#include "openmc/vector.h"
#include "xtensor/xtensor.hpp"
#include <fmt/core.h>
#include <hdf5.h>
#include <cstddef> // for size_t
#include <string>
namespace openmc {
//==============================================================================
// Global variables
//==============================================================================
hid_t track_file; //! HDF5 identifier for track file
hid_t track_dtype; //! HDF5 identifier for track datatype
int n_tracks_written; //! Number of tracks written
//==============================================================================
// Non-member functions
//==============================================================================
void add_particle_track(Particle& p)
{
p.tracks().emplace_back();
p.tracks().back().particle = p.type();
}
void write_particle_track(Particle& p)
{
p.tracks().back().states.push_back(p.get_track_state());
}
void open_track_file()
{
// Open file and write filetype/version -- when MPI is enabled and there is
// more than one rank, each rank writes its own file
#ifdef OPENMC_MPI
std::string filename;
if (mpi::n_procs > 1) {
filename = fmt::format("{}tracks_p{}.h5", settings::path_output, mpi::rank);
} else {
filename = fmt::format("{}tracks.h5", settings::path_output);
}
#else
std::string filename = fmt::format("{}tracks.h5", settings::path_output);
#endif
track_file = file_open(filename, 'w');
write_attribute(track_file, "filetype", "track");
write_attribute(track_file, "version", VERSION_TRACK);
// Create compound type for Position
hid_t postype = H5Tcreate(H5T_COMPOUND, sizeof(struct Position));
H5Tinsert(postype, "x", HOFFSET(Position, x), H5T_NATIVE_DOUBLE);
H5Tinsert(postype, "y", HOFFSET(Position, y), H5T_NATIVE_DOUBLE);
H5Tinsert(postype, "z", HOFFSET(Position, z), H5T_NATIVE_DOUBLE);
// Create compound type for TrackState
track_dtype = H5Tcreate(H5T_COMPOUND, sizeof(struct TrackState));
H5Tinsert(track_dtype, "r", HOFFSET(TrackState, r), postype);
H5Tinsert(track_dtype, "u", HOFFSET(TrackState, u), postype);
H5Tinsert(track_dtype, "E", HOFFSET(TrackState, E), H5T_NATIVE_DOUBLE);
H5Tinsert(track_dtype, "time", HOFFSET(TrackState, time), H5T_NATIVE_DOUBLE);
H5Tinsert(track_dtype, "wgt", HOFFSET(TrackState, wgt), H5T_NATIVE_DOUBLE);
H5Tinsert(
track_dtype, "cell_id", HOFFSET(TrackState, cell_id), H5T_NATIVE_INT);
H5Tinsert(track_dtype, "cell_instance", HOFFSET(TrackState, cell_instance),
H5T_NATIVE_INT);
H5Tinsert(track_dtype, "material_id", HOFFSET(TrackState, material_id),
H5T_NATIVE_INT);
H5Tclose(postype);
}
void close_track_file()
{
H5Tclose(track_dtype);
file_close(track_file);
// Reset number of tracks written
n_tracks_written = 0;
}
bool check_track_criteria(const Particle& p)
{
if (settings::write_all_tracks) {
// Increment number of tracks written and get previous value
int n;
#pragma omp atomic capture
n = n_tracks_written++;
// Indicate that track should be written for this particle
return n < settings::max_tracks;
}
// Check for match from explicit track identifiers
if (settings::track_identifiers.size() > 0) {
for (const auto& t : settings::track_identifiers) {
if (simulation::current_batch == t[0] &&
simulation::current_gen == t[1] && p.id() == t[2]) {
return true;
}
}
}
return false;
}
void finalize_particle_track(Particle& p)
{
// Determine number of coordinates for each particle
vector<int> offsets;
vector<int> particles;
vector<TrackState> tracks;
int offset = 0;
for (auto& track_i : p.tracks()) {
offsets.push_back(offset);
particles.push_back(static_cast<int>(track_i.particle));
offset += track_i.states.size();
tracks.insert(tracks.end(), track_i.states.begin(), track_i.states.end());
}
offsets.push_back(offset);
#pragma omp critical(FinalizeParticleTrack)
{
// Create name for dataset
std::string dset_name = fmt::format("track_{}_{}_{}",
simulation::current_batch, simulation::current_gen, p.id());
// Write array of TrackState to file
hsize_t dims[] {static_cast<hsize_t>(tracks.size())};
hid_t dspace = H5Screate_simple(1, dims, nullptr);
hid_t dset = H5Dcreate(track_file, dset_name.c_str(), track_dtype, dspace,
H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
H5Dwrite(dset, track_dtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, tracks.data());
// Write attributes
write_attribute(dset, "n_particles", p.tracks().size());
write_attribute(dset, "offsets", offsets);
write_attribute(dset, "particles", particles);
// Free resources
H5Dclose(dset);
H5Sclose(dspace);
}
// Clear particle tracks
p.tracks().clear();
}
} // namespace openmc