Getting started
This page takes you from a fresh clone to a dispatch result on screen.
Prerequisites
NemSim targets net10.0 (see NEM.Model/NEM.Model.csproj), so you need the .NET 10 SDK installed.
Nothing else is required to build, test or run the CLI.
Clone, build, test
git clone https://github.com/HasinthaAttanayake/NemSim.git
dotnet build NemSim.slnx
dotnet test NemSim.slnx
The solution file is NemSim.slnx at the repository root. dotnet test runs NEM.Model.Tests,
NEM.CLI.Tests and NEM.Web.Tests.
Configuration
NEM.CLI reads its settings from a JSON file next to the built executable. There are two
candidates, checked in this order:
appsettings.local.json, which is machine-local, gitignored, and absent by default.appsettings.example.json, which is committed and used as the fallback when the local file is absent.
Copy the example to create your own local file:
cp NEM.CLI/appsettings.example.json NEM.CLI/appsettings.local.json
Because the local file is gitignored, editing it never produces a diff for anyone else, and because the example is the fallback, the CLI works out of the box even if you skip this step.
The three settings, from NEM.CLI/Configuration/CliSettings.cs:
| Setting | Meaning |
|---|---|
inputBundleRoot |
Where --validate-inputs and --ingest look for an input bundle by default. |
outputRoot |
Where --ingest writes its artifacts, and the first place a scenario run looks for the demand and weather files a scenario references. Normally NEM.Web/wwwroot/data, the directory the web site reads from. It does not control where scenario results are published. |
defaultScenarioPath |
The scenario configuration --run-scenario uses when you do not pass one explicitly. |
All three are plain strings resolved relative to the solution root at run time, so you can point
inputBundleRoot or outputRoot at a directory outside the repository without NemSim caring where
your shell happens to be. The CLI reference covers how command-line paths are resolved
the same way.
First run
dotnet run --project NEM.CLI -- --run-scenario
With no argument, this loads the scenario at defaultScenarioPath. That is the committed
scenarios/nem-fy2026-all-regions.json, which dispatches all five NEM regions together over
directed interconnectors. It reads the committed demand and weather artifacts for each region
(demand-{region}.json and weather-{region}.json, looked for under outputRoot first and then
under the solution root) and dispatches every hour of the modelled year, sizing storage against the
scenario's reliability standard as it goes.
It writes results.json, results-overview.json, and a results-{region}.json and
results-{region}-overview.json pair for each region. Results always go to
NEM.Web/wwwroot/data, which is a fixed path rather than the configured outputRoot; changing
outputRoot moves where inputs are read from, not where results land. Publication is atomic, so a
failed run never leaves a half-written artifact in place.
A single scenario run dispatches a modelled year in one pass per storage-sizing iteration, so it
finishes quickly enough to iterate on locally rather than being something you queue and walk away
from. You will know it succeeded because the process prints the number of hourly intervals
dispatched and the regions covered, then a line confirming where it wrote the results, and exits
with status 0. If the reliability standard was not met, it also prints a WARNING line naming the
achieved and target unserved-energy percentages. That is not a failure, just a result worth
reading closely.
Viewing results
dotnet run --project NEM.Web
NEM.Web is a Blazor WebAssembly site that reads the JSON artifacts under
NEM.Web/wwwroot/data, the same files --run-scenario writes and --ingest writes to by default.
Open the URL it prints to browse the results you just generated.
Validation runs worth knowing about
Two test runs act as acceptance checks on the model rather than ordinary unit tests. See the "Validation runs" section of the repository README for the exact commands:
- A suite of hand-calculated dispatch fixtures, checked against manually worked figures.
- A synthetic 8,760-hour full-year storage-sizing acceptance test, run in Release mode, which prints solver wall-clock time, dispatch-pass count and the selected Battery capacity.
Where next
- Concepts: what the model actually does.
- Limitations: what it assumes, and where it will mislead you.
- Exploring: designing a study, including sweeps and driving the model with an LLM.