Your First Simulation
A NeoMC calculation has six parts:
materials -> geometry -> observables -> physics package -> source -> runThis tutorial uses a photon slab because the supported coupled-EM resolver shows the complete path from an external data installation to the result.
1. Materials
std::vector<MaterialDefinition> materials =
material_definitions_from_inputs({
MaterialInputDefinition{
.name = "aluminum",
.density_g_cm3 = 2.70,
.temperature_kelvin = 293.6,
.components = {
element_atom_fraction("Al", 1.0),
},
},
});Use element components for element-based EM data. Use explicit nuclides when a nuclear evaluation depends on isotope identity.
2. Geometry
auto geometry = std::make_shared<RectilinearGrid>(
make_rectilinear_grid(
RectilinearGridInputDefinition{
.x_edges = {0.0, 1.0},
.y_edges = {-2.0, 2.0},
.z_edges = {-2.0, 2.0},
.material_names = {"aluminum"},
.observable_regions = {ObservableId{0}},
.region_names = {"target"},
},
materials));Named regions make source restrictions and observable targets readable.
3. Observable
ObservableSetDefinition observables = make_observable_set_definition(
ObservableSetInputDefinition{
.observables = {
ObservableInputDefinition{
.observable_id = ObservableId{0},
.quantity = ObservableQuantity::edep,
.target = ObservableTargetKind::volume,
.region = "target",
},
},
},
*geometry);The observable id identifies this request in the result. response_id distinguishes totals, bins and additional statistics generated for it.
4. Physics Package
Choose the reference profile, then resolve the data required by the material list:
const CoupledEmPhysicsProfile profile =
CoupledEmPhysicsProfile::neomc_reference_epdl_eedl;
CoupledEmSimulationPackage em =
resolve_coupled_em_simulation_package(
CoupledEmDataLibraryDefinition{
.root = physics_data_root,
},
materials,
make_coupled_em_transport_config(profile),
make_coupled_em_material_process_config(profile));The resolver returns the package consumed by SimulationModel. The selected data-library version and consumed source hashes are retained in the result.
5. Source
SimulationSourceDefinition source{
.kind = SimulationSourceKind::independent,
.independent = IndependentSourceDefinition{
.spatial = SourceSpatialDefinition{
.mode = SourceSpatialMode::point,
.position = {1.0e-6, 0.0, 0.0},
},
.angular = SourceAngularDefinition{
.mode = SourceAngularMode::fixed_direction,
.direction = {1.0, 0.0, 0.0},
},
.energy = SourceEnergyDefinition{
.distribution = SourceScalarDistribution{
.mode = SourceScalarDistributionMode::delta,
.value = 1.0e6,
},
},
.particle_type = ParticleType::photon,
.master_seed = 47,
},
};NeoMC uses eV, cm and seconds for these fields.
6. Run
SimulationTransportSessionResult result = run_simulation_model(
SimulationModel{
.geometry = hold_geometry(geometry),
.materials = materials,
.observables = observables,
.packages = SimulationPackageSet{
.coupled_em = std::move(em),
.required_capabilities = {
SimulationRequiredTransportCapability{
.package = TransportPackageId::coupled_em,
.capability = "em_photon_transport",
.minimum_status =
TransportCapabilityStatus::implemented,
},
},
},
.source = std::move(source),
.run = SimulationRunSettings{
.histories = 10000,
.worker_threads = 4,
},
});Compilation checks that the source particle and reachable secondaries have an enabled owner, that the requested capability is available, and that material, geometry, package data and observables are compatible.
7. Inspect The Result
const SimulationObservableRow &row =
require_simulation_observable_row(
result,
TransportPackageId::coupled_em,
"energy_deposit_edep",
"total",
ObservableId{0});Read row.value, row.standard_error, row.units and row.histories together. Also inspect require_simulation_package_result(...) and result.coupled_em_data before preserving or comparing the score.