perf: use compact array format for TRISO particle HDF5 I/O

This commit is contained in:
cn-skywalker 2026-04-10 05:24:08 +00:00
parent a657bcb6c2
commit 2b371c606c
2 changed files with 186 additions and 4 deletions

View file

@ -112,6 +112,10 @@ class Summary:
if "dagmc" not in self._f['geometry'].attrs.keys():
self._read_surfaces()
cell_fills = self._read_cells()
# Read compact TRISO particle data if present
if 'geometry/triso_particles' in self._f:
triso_fills = self._read_triso_particles()
cell_fills.update(triso_fills)
self._read_universes()
self._read_lattices()
self._finalize_geometry(cell_fills)
@ -194,6 +198,69 @@ class Summary:
return cell_fills
def _read_triso_particles(self):
"""Read compact TRISO particle data from HDF5 and reconstruct objects.
Returns
-------
dict
Cell fill information for all TRISO and background cells
"""
triso_grp = self._f['geometry/triso_particles']
n_triso = int(triso_grp.attrs['n_triso'])
if n_triso == 0:
return {}
# Batch-read all arrays
positions = triso_grp['positions'][()] # (N, 4) array
surface_ids = triso_grp['surface_ids'][()] # (N,) array
cell_ids = triso_grp['cell_ids'][()] # (N,) array
fill_universes = triso_grp['fill_universes'][()] # (N,) array
group_offsets = triso_grp['group_offsets'][()] # (n_groups+1,) array
cell_fills = {}
# Create all TRISO Sphere surfaces in batch
for i in range(n_triso):
x0, y0, z0, r = positions[i]
sid = int(surface_ids[i])
surf = openmc.Sphere(x0=float(x0), y0=float(y0),
z0=float(z0), r=float(r),
surface_id=sid)
self._fast_surfaces[sid] = surf
# Create all TRISO Cell objects in batch
for i in range(n_triso):
cid = int(cell_ids[i])
sid = int(surface_ids[i])
fill_univ_id = int(fill_universes[i])
x0, y0, z0, _ = positions[i]
cell = openmc.Cell(cell_id=cid)
cell.region = -self._fast_surfaces[sid]
cell.translation = np.array([x0, y0, z0], dtype=np.float64)
cell_fills[cid] = ('universe', fill_univ_id)
self._fast_cells[cid] = cell
# Create background cells for each group
n_groups = len(group_offsets) - 1
groups_grp = triso_grp['groups']
for g in range(n_groups):
grp = groups_grp[str(g)]
bg_cell_id = int(grp['background_cell_id'][()])
bg_material_id = int(grp['background_material_id'][()])
bg_universe_id = int(grp['background_universe_id'][()])
bg_cell = openmc.Cell(cell_id=bg_cell_id)
bg_cell.virtual_lattice = True
bg_cell.lower_left = list(grp['vl_lower_left'][()])
bg_cell.pitch = list(grp['vl_pitch'][()])
bg_cell.shape = list(grp['vl_shape'][()])
cell_fills[bg_cell_id] = ('material', bg_material_id)
self._fast_cells[bg_cell_id] = bg_cell
return cell_fills
def _read_universes(self):
for group in self._f['geometry/universes'].values():
geom_type = group.get('geom_type')

View file

@ -1,6 +1,7 @@
#include "openmc/summary.h"
#include <fmt/core.h>
#include <map>
#include "openmc/capi.h"
#include "openmc/cell.h"
@ -93,25 +94,139 @@ void write_nuclides(hid_t file)
close_group(macro_group);
}
void write_triso_particles(hid_t geom_group)
{
// Collect all TRISO surfaces and group by background cell ID
std::map<int32_t, vector<int32_t>> bg_to_surfs;
for (int i = 0; i < model::surfaces.size(); ++i) {
const auto& surf = model::surfaces[i];
if (surf->is_triso_surface_) {
bg_to_surfs[surf->triso_base_index_].push_back(i);
}
}
int n_groups = bg_to_surfs.size();
if (n_groups == 0)
return;
// Count total TRISO particles
int n_triso = 0;
for (const auto& [bg_id, surfs] : bg_to_surfs) {
n_triso += surfs.size();
}
// Build flat arrays
vector<double> positions(n_triso * 4);
vector<int32_t> surface_ids(n_triso);
vector<int32_t> cell_ids(n_triso);
vector<int32_t> fill_universes(n_triso);
vector<int32_t> group_offsets(n_groups + 1);
int idx = 0;
int g = 0;
group_offsets[0] = 0;
for (const auto& [bg_cell_id, surfs] : bg_to_surfs) {
for (const auto& i_surf : surfs) {
const auto& surf = model::surfaces[i_surf];
vector<double> center = surf->get_center();
double radius = surf->get_radius();
positions[idx * 4 + 0] = center[0];
positions[idx * 4 + 1] = center[1];
positions[idx * 4 + 2] = center[2];
positions[idx * 4 + 3] = radius;
surface_ids[idx] = surf->id_;
// Get TRISO particle cell via triso_particle_index_
int32_t i_cell = model::cell_map.at(surf->triso_particle_index_);
const auto& cell = model::cells[i_cell];
cell_ids[idx] = cell->id_;
fill_universes[idx] = model::universes[cell->fill_]->id_;
++idx;
}
group_offsets[g + 1] = idx;
++g;
}
// Write compact TRISO data to HDF5
hid_t triso_group = create_group(geom_group, "triso_particles");
write_attribute(triso_group, "n_groups", n_groups);
write_attribute(triso_group, "n_triso", n_triso);
// Write positions as 2D dataset [n_triso, 4]
hsize_t pos_dims[] = {static_cast<hsize_t>(n_triso), 4};
write_dataset_lowlevel(triso_group, 2, pos_dims, "positions",
H5TypeMap<double>::type_id, H5S_ALL, false, positions.data());
write_dataset(triso_group, "surface_ids", surface_ids);
write_dataset(triso_group, "cell_ids", cell_ids);
write_dataset(triso_group, "fill_universes", fill_universes);
write_dataset(triso_group, "group_offsets", group_offsets);
// Write per-group metadata (background cell info)
hid_t groups_group = create_group(triso_group, "groups");
g = 0;
for (const auto& [bg_cell_id, surfs] : bg_to_surfs) {
auto grp = create_group(groups_group, std::to_string(g));
int32_t i_bg_cell = model::cell_map.at(bg_cell_id);
const auto& bg_cell = model::cells[i_bg_cell];
write_dataset(grp, "background_cell_id", bg_cell->id_);
write_dataset(grp, "background_material_id",
model::materials[bg_cell->material_[0]]->id_);
write_dataset(
grp, "background_universe_id", model::universes[bg_cell->universe_]->id_);
write_dataset(grp, "vl_lower_left", bg_cell->vl_lower_left_);
write_dataset(grp, "vl_pitch", bg_cell->vl_pitch_);
write_dataset(grp, "vl_shape", bg_cell->vl_shape_);
close_group(grp);
++g;
}
close_group(groups_group);
close_group(triso_group);
}
void write_geometry(hid_t file)
{
auto geom_group = create_group(file, "geometry");
write_attribute(geom_group, "n_cells", model::cells.size());
write_attribute(geom_group, "n_surfaces", model::surfaces.size());
// Count non-TRISO cells and surfaces for accurate counts
int n_cells = 0;
int n_surfaces = 0;
for (const auto& c : model::cells) {
if (!c->triso_particle_ && !c->virtual_lattice_)
++n_cells;
}
for (const auto& surf : model::surfaces) {
if (!surf->is_triso_surface_)
++n_surfaces;
}
write_attribute(geom_group, "n_cells", n_cells);
write_attribute(geom_group, "n_surfaces", n_surfaces);
write_attribute(geom_group, "n_universes", model::universes.size());
write_attribute(geom_group, "n_lattices", model::lattices.size());
auto cells_group = create_group(geom_group, "cells");
for (const auto& c : model::cells)
for (const auto& c : model::cells) {
if (c->triso_particle_ || c->virtual_lattice_)
continue;
c->to_hdf5(cells_group);
}
close_group(cells_group);
auto surfaces_group = create_group(geom_group, "surfaces");
for (const auto& surf : model::surfaces)
for (const auto& surf : model::surfaces) {
if (surf->is_triso_surface_)
continue;
surf->to_hdf5(surfaces_group);
}
close_group(surfaces_group);
// Write compact TRISO particle data
write_triso_particles(geom_group);
auto universes_group = create_group(geom_group, "universes");
for (const auto& u : model::universes)
u->to_hdf5(universes_group);