Expand description
Sparse 3D voxel tallies of implanted atoms, damage and deposited energy, with CSV and VTK export.
VoxelTally implements BcaTally. It bins events by position on its
own regular grid (VoxelTallyGrid), so it works with any
crate::geometry::Geometry (a crate::geometry::VoxelGrid, a mesh or
a CSG solid), not only with a voxel grid; use
VoxelTallyGrid::from_voxel_grid to tally on the voxels of a grid
target. Build one prototype with VoxelTally::new, hand clones to
crate::ion::bca::Bca::run, and turn the merged tally into a plain-data
VoxelReport with VoxelTally::report.
Units: positions and lengths in metres, energies in eV. x is the depth.
§What is tallied per voxel
implanted: beam particles that came to rest in the voxel (the voxel counterpart ofcrate::tally::ion::RangeReport::stopped).displacements: target atoms displaced in the voxel, counted where the recoil is created (transfer aboveE_d), the simulated cascade count ofcrate::tally::ion::CascadeDefects::displacements. This is the damage measure of the tally. The NRT / Kinchin-Pease model estimate (crate::ion::damage) needs a per-material Lindhard partition and is not tallied per voxel; the two are never conflated (seecrate::ion::damagefor the convention and its sources, Norgett, Robinson and Torrens, Nucl. Eng. Des. 33 (1975) 50, and Lindhard et al., Mat. Fys. Medd. Dan. Vid. Selsk. 33 (1963) no. 10).- Per-element defects, when the tally knows the species of the run (see
VoxelTally::with_species): for every species index of the engine (crate::ion::bca::Bca::species_z), thevacanciesat the displacement site, theinterstitialswhere a displaced atom came to rest without filling a site, and thereplacements. These use the definitions ofcrate::tally::ion::CascadeDefectsand its replacement rule (one shared implementation), so summed over voxels (andVoxelReport::outside) and species they equal that struct’s totals exactly. A replacement is attributed to the species of the atom it replaced, at the site of that atom, sovacancies = displacements - replacementsholds per species and voxel. Beam particles are not interstitials here (they areimplanted). - Deposited energy, split by channel so each can be checked against the
engine’s
crate::ion::bca::EnergyBudget:electronic_ev(nonlocal and local electronic loss),lattice_ev(nuclear energy left in the lattice: subthreshold and weak transfers and the binding energy of displaced atoms) andrest_ev(the kinetic energy of a particle when it stops below its cutoff).VoxelCell::deposited_evis their sum. The work done against the planar surface barrier and the energy carried out of the target are not deposited in any voxel and are not tallied here.
The nonlocal electronic loss of a free flight is spread uniformly along
the straight segment (the engine’s convention, see
crate::ion::bca::BcaTally::electronic), so a segment that crosses
voxel faces is split between the voxels in proportion to the length in
each. Everything else is a point event and goes to the voxel containing
it. Voxels own the half-open box [o + i h, o + (i + 1) h) on each axis;
events outside the grid are summed in VoxelReport::outside.
§Sparse storage
Only voxels that received an event are stored, in a BTreeMap keyed on the
flat index i + nx (j + ny k), so empty voxels cost no memory and
iteration, merging and export follow one fixed order.
§Determinism
Counts are integers and energies are f64 sums, merged voxel by voxel in
the order crate::rng::run_particles calls merge (chunk order). For a
fixed chunk_size the result is bit-identical at any thread count
(lindhard/tests/voxel_tally.rs).
§Export formats
VoxelReport::write_csv writes one row per occupied voxel after a
# key = value header that carries the grid, so the file reads back
(VoxelReport::read_csv) exactly: floats are written in the shortest
form that parses back to the same bits. VoxelReport::write_vtk writes
a legacy ASCII VTK 3.0 UNSTRUCTURED_GRID of VTK_VOXEL cells, one per
occupied voxel (so the file is as sparse as the tally), with the tallies
as cell scalars; format: Kitware, The VTK User’s Guide, 11th ed. (2006),
“VTK File Formats”. The VTK file does not carry the outside sums.
A tally built with VoxelTally::with_species writes format version 2:
the species are named in the header and each adds vacancies,
interstitials and replacements columns (scalars). A tally without
species writes version 1 exactly as before, and both readers accept both
versions.
VoxelReport::read_vtk reads back what write_vtk writes.
Structs§
- Export
Provenance - Where a damage-export file came from: the header keys beyond the grid and the tallies. The CSV is an exchange format; these fields let a reader tie a file to the run that made it.
- Species
Defects - Defects of one species in one voxel (or summed), as defined by
crate::tally::ion::CascadeDefects. - Voxel
Cell - The tallies of one voxel (or of the whole grid, for totals).
- Voxel
Record - One occupied voxel of a
VoxelReport. - Voxel
Report - A
VoxelTallyas plain data. Voxels are in increasing flat-index order (i + nx (j + ny k)). - Voxel
Tally - A sparse voxel tally; see the module docs.
- Voxel
Tally Grid - The regular grid a
VoxelTallybins on:dimsvoxels of edgespacing_mstarting atorigin_m. Voxel(i, j, k)has the flat indexi + nx (j + ny k)(x fastest, as inVoxelGrid).
Enums§
- Voxel
Tally Error - Errors from building a
VoxelTallyGridor reading an exported file.
Constants§
- EXPORT_
BANNER - The banner line of a damage-export file (see
docs/damage-export-format.md). - EXPORT_
FORMAT_ VERSION - Version of the damage-export format, the
format_versionheader key.