Table of Contents

Getting started

This page takes you from a fresh clone to a dispatch result on screen. It is for anyone who wants to run NEMSweep locally.

Everything on this page is NEMSweep.CLI, the command-line tool that ingests raw inputs and runs portable grid scenarios. It accepts custom region IDs through format-2 bundles, as well as National Electricity Market inputs. The framework itself (NEMSweep.Model, NEMSweep.Contracts) has no command line and no data.

For ready-to-edit configurations, see Hosted starters: Simple is the smallest, a synthetic Island-X grid; Advanced is the NEM worked example, preserving real Australian NEM FY2026 AEMO demand, original TMYx EPW weather and the existing five-region fleet/cost/link assumptions. Both are prepared by nemsweep --quick-start. For an immediately local recipe, see Custom grids.

Prerequisites

NEMSweep targets net10.0 (see NEMSweep.Model/NEMSweep.Model.csproj), so a source build needs the .NET 10 SDK, and so does installing the published .NET tool. Nothing else is required to build, test or run the CLI.

To run without a toolchain, use the container image instead. The rest of this page still applies: same commands, same workspace, mounts in place of directories. See Running the container.

Linux

Two things catch a fresh Linux machine out, neither specific to NEMSweep.

No .NET SDK. Where your distribution does not package .NET 10, Microsoft's script installs it into your home directory without root:

curl -fsSL https://dot.net/v1/dotnet-install.sh | bash -s -- --channel 10.0
export DOTNET_ROOT="$HOME/.dotnet"
export PATH="$PATH:$DOTNET_ROOT:$DOTNET_ROOT/tools"

PATH after a tool install. dotnet tool install --global writes to ~/.dotnet/tools, which a fresh shell does not search, so nemsweep comes back as command not found even though the install reported success:

export PATH="$PATH:$HOME/.dotnet/tools"

Put either export in your shell profile to make it persist.

ICU. .NET needs the ICU libraries for globalization, and a minimal container or cloud image often ships without them. The symptom is a System.Globalization stack trace on first run rather than a clear message. Install them with the distribution's own package:

sudo apt-get update && sudo apt-get install -y libicu-dev
sudo dnf install -y libicu

Install without cloning

If you only want to run NEMSweep, install the NEMSweep.CLI .NET tool rather than building from source. These docs target 0.3.0; installation requires its publication (see the release target notice). Pin the version you want to reproduce:

dotnet tool install --global NEMSweep.CLI --version 0.3.0
nemsweep --version

The second command confirms the install and prints NEMSweep.CLI 0.3.0+<commit>.

Everything below is then nemsweep <command> in place of dotnet run --project NEMSweep.CLI -- <command>, and the workspace is configured with --data-root and --output or their environment variables rather than with a settings file next to a build. To build against the framework instead of running it, add the NEMSweep.Model and NEMSweep.Contracts packages to your own project:

dotnet add package NEMSweep.Model --version 0.3.0
dotnet add package NEMSweep.Contracts --version 0.3.0

Use the same package version for both references. Later releases are opt-in: replace 0.3.0 only when you intend to upgrade, then rerun your tests and scenario validation.

Clone, build, test

A source build reports the VersionPrefix in Directory.Build.props, and a release takes its version from the v* tag instead. DocumentedCliVersion pins the release targeted by the install snippets above; neither property confirms that the packages have been published.

git clone https://github.com/HasinthaAttanayake/NEMSweep.git
dotnet build NEMSweep.slnx
dotnet test NEMSweep.slnx

The solution file is NEMSweep.slnx at the repository root. dotnet test runs NEMSweep.Model.Tests and NEMSweep.CLI.Tests.

Configure the workspace

NEMSweep.CLI reads its settings from a JSON file next to the built executable. Two files are candidates, checked in this order:

  1. appsettings.local.json: machine-local, gitignored, absent by default.
  2. appsettings.example.json: committed, and used as the fallback when the local file is absent.

Copy the example to create your own local file:

cp NEMSweep.CLI/appsettings.example.json NEMSweep.CLI/appsettings.local.json

The local file is gitignored, so editing it never produces a diff for anyone else. The example is the fallback, so the CLI runs out of the box even if you skip this step.

The four settings, defined in NEMSweep.CLI/Configuration/CliSettings.cs:

Setting Type Required Meaning
inputBundleRoot string yes Where --validate-inputs and --ingest look for an input bundle by default.
dataRoot string yes Where a scenario's demand and weather artifacts are read from, and where --ingest writes them.
outputRoot string yes Where dispatch results and sweep artifacts are written.
defaultScenarioPath string yes The scenario config --run-scenario uses when you do not pass one.

All four are resolved relative to your current working directory at run time, so any of them can point outside the repository. dataRoot and outputRoot can also be overridden per run with --data-root and --output, or with NEMSWEEP_DATA_ROOT and NEMSWEEP_OUTPUT; the CLI reference covers the precedence.

outputRoot in the committed appsettings.example.json is a gitignored out/, so your results land where they do not disturb published ones. dataRoot is the setting you have to supply: the example still points it at NEMSweep.Web/wwwroot/data, a path the repository no longer contains, and the demand and weather artifacts are not carried here in any case. Set it to wherever you ingest them, or pass --data-root per run.

Ingest the input artifacts

Building your own input bundle? Start with AEMO NEMWeb demand and Climate.OneBuilding EPW weather. That guide covers source selection, unchanged files, typical-year provenance and the separate data-attribution/licensing requirements.

A scenario reads a demand-{region}.json and a weather-{region}.json per region, plus the generation fleet defined in its scenario configuration. The demand and weather artifacts are produced, not committed: assemble a current format-2 input bundle of demand archives and EPW weather files, then run

dotnet run --project NEMSweep.CLI -- --validate-inputs
dotnet run --project NEMSweep.CLI -- --ingest

--validate-inputs writes nothing and reports what it found. --ingest runs the same checks and then writes the artifacts into the data root. Input bundles covers the bundle shape, the manifest, and which upstream file supplies what.

Legacy format 1 only: existing NEM bundles additionally contain an AEMO Generation Information workbook. Their ingestion produces generation-information.json for legacy generation-information commands. Format-2 ingestion and scenario runs do not require that workbook or artifact; scenario configuration supplies the fleet.

Run your first scenario

dotnet run --project NEMSweep.CLI -- --run-scenario

With no argument, --run-scenario loads the scenario at defaultScenarioPath. In the committed settings that is scenarios/nem-fy2026-all-regions.json, which dispatches all five NEM regions together over directed interconnectors. It reads demand-{region}.json and weather-{region}.json for each region from the data root, dispatches every hour of the modelled year, and sizes battery storage against the scenario's reliability standard as it goes.

The run writes results.json, results-overview.json, and a results-{region}.json and results-{region}-overview.json pair for each region, all under the output root. Publication is atomic, so a failed run never leaves a half-written artifact in place. See Outputs and provenance for the artifact map.

To send a run elsewhere, name the output directory:

dotnet run --project NEMSweep.CLI -- --run-scenario --output ./my-study

That is also how the results displayed by the separate results site are refreshed: publish the output when you intend to update what it shows, and keep ordinary study output in your own directory.

Add --csv and the run also writes its results as CSV tables, which is what you want if the numbers are going anywhere other than back into NEMSweep.

A scenario run re-dispatches the whole modelled year for each candidate battery size the sizing search tries, so its runtime is one dispatch multiplied by the number of passes the search takes. It still finishes quickly enough to iterate on locally. On success the process prints the number of hourly intervals dispatched and the regions covered, then the path it wrote the results to, 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 a result worth reading closely, not a failure, and the exit code is still 0.

Start from a smaller scenario

The published scenarios/nem-fy2026-all-regions.json is a worked example of a real system, and it is 746 lines because a real system is. Two shorter ways in:

scenarios/starter-nsw1.json is the same NSW1 assets on their own, 176 lines, and it runs the same way:

dotnet run --project NEMSweep.CLI -- --run-scenario scenarios/starter-nsw1.json

Change one number in it, run it again, and watch one number move in the result.

For a blank starting point, --new-scenario prints the smallest configuration that runs: one region, one generating fleet, one storage fleet. It writes to standard output, so redirect it to a file:

dotnet run --project NEMSweep.CLI -- --new-scenario > scenarios/mine.json

Or write a sweep

A sweep is often less work than a scenario. A sweep is a baseline scenario config plus a set of points, each point a small override patch on that baseline, lined up along one labelled axis. You do not author a system: you take one that exists and vary it.

"What happens as I vary this" is a sweep. "Here is a system I designed" is a scenario. If your question is the first kind, read Sweeps before Scenario configuration. Copy sweeps/datacentre-nameplate-fy2026.json, change the numbers, and validate before spending time on dispatch:

dotnet run --project NEMSweep.CLI -- --fan-out-sweep sweeps/my-sweep.json

--fan-out-sweep applies every point's patch to the baseline and validates each resulting config without running any dispatch, so a bad override surfaces immediately.

Where next

  • CLI reference: every command, its arguments, and how the workspace roots are chosen.
  • Glossary: the vocabulary, if a term above went past you.
  • Concepts: what the model does, stage by stage.
  • Limitations: what the model assumes, and where it will mislead you.
  • Exploring: designing a study, including sweeps and driving the model with an LLM.