Skip to content

Your First Simulation

A NeoMC calculation has six parts:

text
materials -> geometry -> observables -> physics package -> source -> run

This 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

cpp
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

cpp
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

cpp
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:

cpp
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

cpp
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

cpp
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

cpp
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.

NeoMC user documentation.