Observables
Observables define what the simulation measures. Build ObservableSetInputDefinition, bind names to a concrete geometry with make_observable_set_definition, and pass the result to SimulationModel.
Events And Quantities
The current valid pairs are defined directly by the public enums and runtime validation:
| Event | Quantities |
|---|---|
energy_deposit | edep, dose, hits |
track_step | track_length, track_length_flux, response_weighted_flux, microscopic_reaction_rate, microscopic_differential_reaction_rate |
boundary_crossing | surface_current, surface_flux, surface_angular_current, crossing_count, hits |
point_flux | point_flux, response_weighted_flux, microscopic_reaction_rate |
secondary_handoff | hits |
nuclear_reaction | secondary_multiplicity |
nuclear_reaction_secondary | hits, secondary_energy |
history_end | pulse_height, linear_combination |
coincidence_count is produced by a HistoryCoincidenceDefinition, not authored as a direct event/quantity pair.
Estimators
analog: score sampled deposits, steps, crossings, products or completed history responses.expected_value: score a conditional response such as point flux, microscopic reaction rate, differential reaction rate or detector-response folding.derived: created by a history-level linear combination.
The runtime rejects an estimator that is not implemented for the requested event and quantity.
Targets
Targets are:
any;volume, selected by named region or observable-region id;boundary;plane, with normal, offset, tolerance and crossing direction;point, optionally averaged over a finite cylinder or sphere.
Plane observables can define a circular aperture. Point estimators can select source, collision, positron-annihilation or photoelectric-relaxation contributions where the package supports that origin.
Axes
Available axes are:
- energy;
- direction cosine
mu; - surface-relative cosine
surface_mu; - signed projected surface angle;
- time;
- x, y and z position;
- multiplicity.
Every axis uses explicit increasing edges. The supported axes depend on the event. Spatial track-step meshes split path segments at each crossed mesh plane instead of assigning a whole step to its midpoint.
An energy axis can apply a Gaussian detector response with GaussianEnergyResponseDefinition. response_weighted_flux instead folds a tabulated energy response into the estimator.
Common Definitions
Volume dose:
ObservableInputDefinition{
.observable_id = ObservableId{1},
.event = ObservableEventKind::energy_deposit,
.quantity = ObservableQuantity::dose,
.target = ObservableTargetKind::volume,
.region = "detector",
.mass_g = detector_mass_g,
};Surface current:
ObservableInputDefinition{
.observable_id = ObservableId{2},
.event = ObservableEventKind::boundary_crossing,
.quantity = ObservableQuantity::surface_current,
.particle = ParticleType::neutron,
.target = ObservableTargetKind::plane,
.plane_normal = {1.0, 0.0, 0.0},
.plane_offset_cm = 10.0,
};Runtime-bound microscopic reaction rate:
ObservableInputDefinition{
.observable_id = ObservableId{3},
.event = ObservableEventKind::track_step,
.quantity = ObservableQuantity::microscopic_reaction_rate,
.estimator = ObservableEstimator::expected_value,
.particle = ParticleType::neutron,
.target = ObservableTargetKind::volume,
.region = "foil",
.volume_cm3 = foil_volume_cm3,
.target_nuclide = al27,
.mt = 107,
};For an evaluated microscopic response, model compilation binds the response from the same package data used by transport. The observable does not carry a second private cross-section table.
Differential elastic response:
ObservableInputDefinition{
.observable_id = ObservableId{4},
.event = ObservableEventKind::track_step,
.quantity =
ObservableQuantity::microscopic_differential_reaction_rate,
.estimator = ObservableEstimator::expected_value,
.particle = ParticleType::alpha,
.target = ObservableTargetKind::volume,
.region = "helium",
.volume_cm3 = target_volume_cm3,
.target_nuclide = he4,
.mt = 2,
.microscopic_reaction_direction_cosine = 0.5,
.microscopic_reaction_reference_frame =
ReactionSecondaryReferenceFrame::center_of_mass,
};The reference frame is part of the observable. Current neutron differential elastic responses use the laboratory frame; evaluated alpha two-body MT2 responses use the center-of-mass frame. Compilation binds the differential cross section to the evaluated angular law in the transport package.
History-Level Derived Results
HistoryLinearCombinationDefinition combines source bins before second moments are accumulated. Use it when covariance matters, such as molecular stoichiometry or an activation response assembled from several cells.
ObservableSetInputDefinition input{
.observables = {
ObservableInputDefinition{
.observable_id = ObservableId{10},
.event = ObservableEventKind::track_step,
.quantity =
ObservableQuantity::microscopic_reaction_rate,
.estimator = ObservableEstimator::expected_value,
.particle = ParticleType::neutron,
.target = ObservableTargetKind::volume,
.region = "cell-a",
.volume_cm3 = cell_a_volume_cm3,
.target_nuclide = target_nuclide,
.mt = 102,
},
ObservableInputDefinition{
.observable_id = ObservableId{11},
.event = ObservableEventKind::track_step,
.quantity =
ObservableQuantity::microscopic_reaction_rate,
.estimator = ObservableEstimator::expected_value,
.particle = ParticleType::neutron,
.target = ObservableTargetKind::volume,
.region = "cell-b",
.volume_cm3 = cell_b_volume_cm3,
.target_nuclide = target_nuclide,
.mt = 102,
},
},
.history_linear_combinations = {
HistoryLinearCombinationDefinition{
.observable_id = ObservableId{20},
.response_id = "combined-production-rate",
.units = "reactions/source",
.terms = {
HistoryLinearCombinationTerm{
.source_observable_id = ObservableId{10},
.source_bin = 0,
.coefficient = 1.0,
},
HistoryLinearCombinationTerm{
.source_observable_id = ObservableId{11},
.source_bin = 0,
.coefficient = 2.0,
},
},
},
},
};HistoryCoincidenceDefinition multiplies two pulse-height-bin responses within each history. It preserves correlation between emissions from the same source event.
input.history_coincidences.push_back(
HistoryCoincidenceDefinition{
.observable_id = ObservableId{30},
.response_id = "detector-a-and-b",
.units = "count/source",
.first_pulse_height_observable_id = ObservableId{1},
.first_bin = 4,
.second_pulse_height_observable_id = ObservableId{2},
.second_bin = 7,
});Combining already reduced means and standard errors cannot recover this covariance.
Result Rows
Each SimulationObservableRow carries:
- package, observable id, type, response id and estimator;
- mean, standard error, units and history counts;
- score sums and squared sums;
- active bin bounds;
- physical response identity and reaction metadata where applicable.
Use find_simulation_observable_rows for a set of bins and require_simulation_observable_row for one required response.
const SimulationObservableRow &total =
require_simulation_observable_row(
result,
TransportPackageId::coupled_em,
"energy_deposit_edep",
"total",
ObservableId{0});
std::cout << total.value << " +/- " << total.standard_error
<< " " << total.units << '\n';
for (const SimulationObservableRow *bin :
find_simulation_observable_rows(
result,
TransportPackageId::coupled_em,
"energy_deposit_edep",
ObservableId{1})) {
std::cout << bin->energy_min_ev << ','
<< bin->energy_max_ev << ','
<< bin->value << ','
<< bin->standard_error << '\n';
}