Skip to content

Commit cd5cd35

Browse files
Addition of a collision tracking feature (#3417)
Co-authored-by: Paul Romano <paul.k.romano@gmail.com>
1 parent 50bb0df commit cd5cd35

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+2268
-148
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ list(APPEND libopenmc_SOURCES
338338
src/cell.cpp
339339
src/chain.cpp
340340
src/cmfd_solver.cpp
341+
src/collision_track.cpp
341342
src/cross_sections.cpp
342343
src/dagmc.cpp
343344
src/distribution.cpp
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
.. _io_collision_track:
2+
3+
===========================
4+
Collision Track File Format
5+
===========================
6+
7+
When collision tracking is enabled with ``mcpl=false`` (the default), OpenMC
8+
writes binary data to an HDF5 file named ``collision_track.h5``. The same data
9+
may also be written after each batch when multiple files are requested
10+
(``collision_track.N.h5``) or when the run is performed in parallel. The file
11+
contains the information needed to reconstruct each recorded collision.
12+
13+
The current revision of the collision track file format is 1.0.
14+
15+
**/**
16+
17+
:Attributes:
18+
- **filetype** (*char[]*) -- String indicating the type of file.
19+
For collision-track files the value is ``"collision_track"``.
20+
21+
:Datasets:
22+
23+
- **collision_track_bank** (Compound type) -- Collision information
24+
for each stored event. Each entry in the dataset corresponds to one
25+
collision and contains the following fields:
26+
27+
- ``r`` (*double[3]*) -- Position of the collision in [cm].
28+
- ``u`` (*double[3]*) -- Direction unit vector immediately after the collision.
29+
- ``E`` (*double*) -- Incident particle energy before the collision in [eV].
30+
- ``dE`` (*double*) -- Energy loss over the collision (:math:`E_\text{before} - E_\text{after}`) in [eV].
31+
- ``time`` (*double*) -- Time of the collision in [s].
32+
- ``wgt`` (*double*) -- Particle weight at the collision.
33+
- ``event_mt`` (*int*) -- ENDF MT number identifying the reaction.
34+
- ``delayed_group`` (*int*) -- Delayed neutron group index (non-zero for delayed events).
35+
- ``cell_id`` (*int*) -- ID of the cell in which the collision occurred.
36+
- ``nuclide_id`` (*int*) -- ZA identifier of the nuclide (ZZZAAAM format).
37+
- ``material_id`` (*int*) -- ID of the material containing the collision site.
38+
- ``universe_id`` (*int*) -- ID of the universe containing the collision site.
39+
- ``n_collision`` (*int*) -- Collision counter for the particle history.
40+
- ``particle`` (*int*) -- Particle type (0=neutron, 1=photon, 2=electron, 3=positron).
41+
- ``parent_id`` (*int64*) -- Unique ID of the parent particle.
42+
- ``progeny_id`` (*int64*) -- Progeny ID of the particle.
43+
44+
In an MPI run, OpenMC writes the combined dataset by gathering collision-track
45+
entries from all ranks before flushing them to disk, so the final file appears
46+
as though it were produced serially.

docs/source/io_formats/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ Output Files
4444

4545
statepoint
4646
source
47+
collision_track
4748
summary
4849
properties
4950
depletion_results

docs/source/io_formats/settings.rst

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,85 @@ source neutrons.
2020

2121
*Default*: None
2222

23+
-----------------------------
24+
``<collision_track>`` Element
25+
-----------------------------
26+
27+
The ``<collision_track>`` element indicates to track information about particle
28+
collisions based on a set of criteria and store these events in a file named
29+
``collision_track.h5``. This file records details such as the position of the
30+
interaction, direction of the incoming particle, incident energy and deposited
31+
energy, weight, time of the interaction, and the delayed neutron group (0 for
32+
prompt neutrons). Additional information such as the cell ID, material ID,
33+
universe ID, nuclide ZAID, particle type, and event MT number are also stored.
34+
Users can specify one or more criterion to filter collisions. If no criteria are
35+
specified, it defaults to tracking all collisions across the model.
36+
37+
.. warning::
38+
Storing all collisions can be very memory intensive. For more targeted
39+
tracking, users can employ a variety of parameters such as ``cell_ids``,
40+
``reactions``, ``universe_ids``, ``material_ids``, ``nuclides``, and
41+
``deposited_E_threshold`` to refine the selection of particle interactions
42+
to be banked.
43+
44+
This element can contain one or more of the following attributes or
45+
sub-elements:
46+
47+
:max_collisions:
48+
An integer indicating the maximum number of collisions to be banked per file.
49+
50+
*Default*: 1000
51+
52+
:max_collision_track_files:
53+
An integer indicating the number of collision_track files to be used.
54+
55+
*Default*: 1
56+
57+
:mcpl:
58+
An optional boolean to enable MCPL_-format instead of the native HDF5-based
59+
format. If activated, the output file name and type is changed to
60+
``collision_track.mcpl``.
61+
62+
*Default*: false
63+
64+
.. _MCPL: https://mctools.github.io/mcpl/mcpl.pdf
65+
66+
:cell_ids:
67+
A list of integers representing cell IDs to define specific cells in which
68+
collisions are to be banked.
69+
70+
*Default*: None
71+
72+
:universe_ids:
73+
A list of integers representing the universe IDs to define specific
74+
universes in which collisions are to be banked.
75+
76+
*Default*: None
77+
78+
:material_ids:
79+
A list of integers representing the material IDs to define specific
80+
materials in which collisions are to be banked.
81+
82+
*Default*: None
83+
84+
:nuclides:
85+
A list of strings representing the nuclide, to define specific
86+
define specific target nuclide collisions to be banked.
87+
88+
*Default*: None
89+
90+
:reactions:
91+
A list of integers representing the ENDF-6 format MT numbers or strings
92+
(e.g. (n,fission)) to define specific reaction types to be banked.
93+
94+
*Default*: None
95+
96+
:deposited_E_threshold:
97+
A float defining the minimum deposited energy per collision (in eV) to
98+
trigger banking.
99+
100+
*Default*: 0.0
101+
23102
----------------------------------
24103
``<confidence_intervals>`` Element
25104
----------------------------------

docs/source/pythonapi/base.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,9 @@ Post-processing
216216
:nosignatures:
217217
:template: myfunction.rst
218218

219+
openmc.read_collision_track_file
220+
openmc.read_collision_track_hdf5
221+
openmc.read_collision_track_mcpl
219222
openmc.voxel_to_vtk
220223

221224
The following classes and functions are used for functional expansion reconstruction.

docs/source/usersguide/settings.rst

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,62 @@ instance, whereas the :meth:`openmc.Track.filter` method returns a new
756756
track_files = [f"tracks_p{rank}.h5" for rank in range(32)]
757757
openmc.Tracks.combine(track_files, "tracks.h5")
758758

759+
Collision Track File
760+
---------------------
761+
762+
OpenMC can generate a collision track file that contains detailed collision
763+
information (position, direction, energy, deposited energy, time, weight, cell
764+
ID, material ID, universe ID, nuclide ZAID, particle type, particle delayed
765+
group and particle ID) for each particle collision depending on user-defined
766+
parameters. To invoke this feature, set the
767+
:attr:`~openmc.Settings.collision_track` attribute as shown in this example::
768+
769+
settings.collision_track = {
770+
"max_collisions": 300,
771+
"reactions": ["(n,fission)", "(n,2n)"],
772+
"material_ids": [1,2],
773+
"nuclides": ["U238", "O16"],
774+
"cell_ids": [5, 12]
775+
}
776+
777+
In this example, collision track information is written to the
778+
collision_track.h5 file at the end of the simulation. The file contains
779+
300 recorded collisions that occurred in materials with IDs 1 or 2, involving
780+
fission or (n,2n) reactions on the nuclides U-238 or O-16, within cells
781+
with IDs 5 and 12.
782+
The file can be read using :func:`openmc.read_collision_track_file`.
783+
The example below shows how to extract the data from the collision_track
784+
feature and displays the fields stored in the file:
785+
786+
>>> data = openmc.read_collision_track_file('collision_track.h5')
787+
>>> data.dtype
788+
dtype([('r', [('x', '<f8'), ('y', '<f8'), ('z', '<f8')]),
789+
('u', [('x', '<f8'), ('y', '<f8'), ('z', '<f8')]), ('E', '<f8'),
790+
('dE', '<f8'), ('time', '<f8'), ('wgt', '<f8'), ('event_mt', '<i4'),
791+
('delayed_group', '<i4'), ('cell_id', '<i4'), ('nuclide_id', '<i4'),
792+
('material_id', '<i4'), ('universe_id', '<i4'), ('n_collision', '<i4'),
793+
('particle', '<i4'), ('parent_id', '<i8'), ('progeny_id', '<i8')])
794+
795+
796+
The full list of fields is as follows:
797+
798+
:r: Position (each direction in [cm])
799+
:u: Direction
800+
:E: Energy in [eV]
801+
:dE: Energy deposited during collision in [eV]
802+
:time: Time in [s]
803+
:wgt: Weight of the particle
804+
:event_mt: Reaction MT number
805+
:delayed_group: Delayed group of the particle
806+
:cell_id: Cell ID
807+
:nuclide_id: Nuclide ID (10000×Z + 10×A + M)
808+
:material_id: Material ID
809+
:universe_id: Universe ID
810+
:n_collision: Number of collision suffered by the particle
811+
:particle: Particle type
812+
:parent_id: Source particle ID
813+
:progeny_id: Progeny ID
814+
759815
-----------------------
760816
Restarting a Simulation
761817
-----------------------

include/openmc/bank.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ extern vector<SourceSite> source_bank;
2020

2121
extern SharedArray<SourceSite> surf_source_bank;
2222

23+
extern SharedArray<CollisionTrackSite> collision_track_bank;
24+
2325
extern SharedArray<SourceSite> fission_bank;
2426

2527
extern vector<vector<int>> ifp_source_delayed_group_bank;

include/openmc/bank_io.h

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
#ifndef OPENMC_BANK_IO_H
2+
#define OPENMC_BANK_IO_H
3+
4+
#include "hdf5.h"
5+
6+
#include "openmc/message_passing.h"
7+
#include "openmc/span.h"
8+
#include "openmc/vector.h"
9+
10+
#include <algorithm>
11+
12+
#ifdef OPENMC_MPI
13+
#include <mpi.h>
14+
#endif
15+
16+
namespace openmc {
17+
18+
template<typename SiteType>
19+
void write_bank_dataset(const char* dataset_name, hid_t group_id,
20+
span<SiteType> bank, const vector<int64_t>& bank_index, hid_t banktype
21+
#ifdef OPENMC_MPI
22+
,
23+
MPI_Datatype mpi_dtype
24+
#endif
25+
)
26+
{
27+
int64_t dims_size = bank_index.back();
28+
int64_t count_size = bank_index[mpi::rank + 1] - bank_index[mpi::rank];
29+
30+
#ifdef PHDF5
31+
hsize_t dims[] {static_cast<hsize_t>(dims_size)};
32+
hid_t dspace = H5Screate_simple(1, dims, nullptr);
33+
hid_t dset = H5Dcreate(group_id, dataset_name, banktype, dspace, H5P_DEFAULT,
34+
H5P_DEFAULT, H5P_DEFAULT);
35+
36+
hsize_t count[] {static_cast<hsize_t>(count_size)};
37+
hid_t memspace = H5Screate_simple(1, count, nullptr);
38+
39+
hsize_t start[] {static_cast<hsize_t>(bank_index[mpi::rank])};
40+
H5Sselect_hyperslab(dspace, H5S_SELECT_SET, start, nullptr, count, nullptr);
41+
42+
hid_t plist = H5Pcreate(H5P_DATASET_XFER);
43+
H5Pset_dxpl_mpio(plist, H5FD_MPIO_COLLECTIVE);
44+
45+
H5Dwrite(dset, banktype, memspace, dspace, plist, bank.data());
46+
47+
H5Sclose(dspace);
48+
H5Sclose(memspace);
49+
H5Dclose(dset);
50+
H5Pclose(plist);
51+
#else
52+
if (mpi::master) {
53+
hsize_t dims[] {static_cast<hsize_t>(dims_size)};
54+
hid_t dspace = H5Screate_simple(1, dims, nullptr);
55+
hid_t dset = H5Dcreate(group_id, dataset_name, banktype, dspace,
56+
H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
57+
58+
#ifdef OPENMC_MPI
59+
vector<SiteType> temp_bank {bank.begin(), bank.end()};
60+
#endif
61+
62+
for (int i = 0; i < mpi::n_procs; ++i) {
63+
hsize_t count[] {static_cast<hsize_t>(bank_index[i + 1] - bank_index[i])};
64+
hid_t memspace = H5Screate_simple(1, count, nullptr);
65+
66+
#ifdef OPENMC_MPI
67+
if (i > 0) {
68+
MPI_Recv(bank.data(), count[0], mpi_dtype, i, i, mpi::intracomm,
69+
MPI_STATUS_IGNORE);
70+
}
71+
#endif
72+
73+
hid_t dspace_rank = H5Dget_space(dset);
74+
hsize_t start[] {static_cast<hsize_t>(bank_index[i])};
75+
H5Sselect_hyperslab(
76+
dspace_rank, H5S_SELECT_SET, start, nullptr, count, nullptr);
77+
78+
H5Dwrite(dset, banktype, memspace, dspace_rank, H5P_DEFAULT, bank.data());
79+
80+
H5Sclose(memspace);
81+
H5Sclose(dspace_rank);
82+
}
83+
84+
H5Dclose(dset);
85+
86+
#ifdef OPENMC_MPI
87+
std::copy(temp_bank.begin(), temp_bank.end(), bank.begin());
88+
#endif
89+
}
90+
#ifdef OPENMC_MPI
91+
else {
92+
if (!bank.empty()) {
93+
MPI_Send(
94+
bank.data(), bank.size(), mpi_dtype, 0, mpi::rank, mpi::intracomm);
95+
}
96+
}
97+
#endif
98+
#endif
99+
}
100+
101+
} // namespace openmc
102+
103+
#endif // OPENMC_BANK_IO_H

include/openmc/collision_track.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#ifndef OPENMC_COLLISION_TRACK_H
2+
#define OPENMC_COLLISION_TRACK_H
3+
4+
#include <string>
5+
6+
namespace openmc {
7+
8+
class Particle;
9+
10+
//! Reserve space in the collision track bank according to user settings.
11+
void collision_track_reserve_bank();
12+
13+
//! Write collision track data to disk when the bank is full or the batch ends.
14+
void collision_track_flush_bank();
15+
16+
//! Record the current particle as a collision-track entry when applicable.
17+
//!
18+
//! \param particle Particle whose collision should be recorded if eligible
19+
void collision_track_record(Particle& particle);
20+
21+
} // namespace openmc
22+
23+
#endif // OPENMC_COLLISION_TRACK_H

include/openmc/constants.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ constexpr array<int, 2> VERSION_VOXEL {2, 0};
3434
constexpr array<int, 2> VERSION_MGXS_LIBRARY {1, 0};
3535
constexpr array<int, 2> VERSION_PROPERTIES {1, 1};
3636
constexpr array<int, 2> VERSION_WEIGHT_WINDOWS {1, 0};
37+
constexpr array<int, 2> VERSION_COLLISION_TRACK {1, 0};
3738

3839
// ============================================================================
3940
// ADJUSTABLE PARAMETERS

0 commit comments

Comments
 (0)