Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction

MUSE 2.0 is a tool for running simulations of energy systems, written in Rust. It is a slimmer and faster version of the older MUSE tool. To get started, please look at the user guide and the command line help.

For an overview of the model, see the model description and the dispatch optimisation formulation. For a list of relevant terms, see the glossary.

If you are a developer, please see the developer guide.

User Guide

Running MUSE 2.0

Once you have installed MUSE 2.0, you should be able to run it via the muse2 command-line program. For details of the command-line interface, see here.

You can also configure the behaviour of MUSE 2.0 by creating a settings.toml file. For more information, see the documentation for this file.

Setting the log level

MUSE uses the fern crate for logging. The default log level is info, though this can be configured either via the log_level option in settings.toml or by setting the MUSE2_LOG_LEVEL environment variable. (If both are used, the environment variable takes precedence.)

The possible options are:

  • error
  • warn
  • info
  • debug
  • trace
  • off

By default, MUSE will colourise the log output if this is available (i.e. it is outputting to a terminal rather than a file).

For more information, please consult the fern documentation.

Command-Line Help for muse2

This document contains the help content for the muse2 command-line program.

Command Overview:

muse2

A tool for running simulations of energy systems

Usage: muse2 [COMMAND]

Subcommands:
  • run — Run a simulation model
  • example — Manage example models

muse2 run

Run a simulation model

Usage: muse2 run [OPTIONS] <MODEL_DIR>

Arguments:
  • <MODEL_DIR> — Path to the model directory
Options:
  • -o, --output-dir <OUTPUT_DIR> — Directory for output files
  • --debug-model — Whether to write additional information to CSV files

muse2 example

Manage example models

Usage: muse2 example <COMMAND>

Subcommands:
  • list — List available examples
  • extract — Extract an example model configuration to a new directory
  • run — Run an example

muse2 example list

List available examples

Usage: muse2 example list

muse2 example extract

Extract an example model configuration to a new directory

Usage: muse2 example extract <NAME> [NEW_PATH]

Arguments:
  • <NAME> — The name of the example to extract
  • <NEW_PATH> — The destination folder for the example

muse2 example run

Run an example

Usage: muse2 example run [OPTIONS] <NAME>

Arguments:
  • <NAME> — The name of the example to run
Options:
  • -o, --output-dir <OUTPUT_DIR> — Directory for output files
  • --debug-model — Whether to write additional information to CSV files

This document was generated automatically by clap-markdown.

File Formats

The following chapters describe the formats for the various files that MUSE 2.0 consumes/produces. Files are either in CSV or TOML format.

Program settings: settings.toml

User settings for MUSE 2.0. Note that these settings do not include model parameters, which are found in model.toml instead.

All settings are optional. If the settings.toml file does not exist, the default settings will be used.

The settings.toml file must be in the current working directory.

Top-level table

FieldDescriptionNotes
log_levelThe program's log levelOptional. Defaults to info.

Must be one of error, warn, info, debug, trace or off (case insensitive)
debug_modelWhether to include extra debugging information in the model outputOptional. Defaults to false.

This includes raw values such as commodity balance duals, which may be useful for debugging the model or understanding results in more detail.

Input files

This file contains information about the file formats for MUSE 2.0 input files.

Model parameters: model.toml

Parameters which affect the behaviour of the model. Most are optional.

Top-level table

FieldDescriptionNotes
milestone_yearsThe milestone years for the simulationMust be positive integers that are sorted and unique
candidate_asset_capacityCapacity to give to candidate assets in dispatch optimisationOptional. Defaults to 0.0001.

The default value should work. Do not change this value unless you know what you're doing!
capacity_limit_factorA factor which constrains the maximum capacity given to candidate assetsOptional. Defaults to 0.1.

This is the proportion of the maximum required capacity across time slices (for a given asset/commodity etc. combination).
pricing_strategyChange the algorithm used for calculating commodity pricesOptional. Defaults to shadow_prices.

The shadow_prices option just uses the shadow prices for commodity prices.

The scarcity_adjusted option adjusts prices for scarcity. This may cause price instability for assets with more than one output commodity. Do not use this unless you know what you're doing!
value_of_lost_loadThe cost applied to unmet demandOptional. Defaults to 1e9.

Currently this only applies to the LCOX appraisal.

Time slices

time_slices.csv

Time slices define how the year is divided up. Each time slice is composed of a season and a time of day. Often, this is written separated by a dot (e.g. winter.day).

FieldDescriptionNotes
seasonName of season
time_of_dayName of time of day
fractionFraction of yearMust be >0 and <=1

Notes

  • The fractions for the different time slices must sum to one.

Regions

regions.csv

Describes regions in the system.

FieldDescriptionNotes
idA unique identifier for a region
descriptionA human-readable label for the region

Agents

agent_commodity_portions.csv

Portions of commodity demand for which agents are responsible.

FieldDescriptionNotes
agent_idThe agent to apply these values to
commodity_idThe commodity for which the agent is responsible
yearsThe year(s) to which this entry appliesOne or more milestone years separated by semicolons or all
commodity_portionPortion of commodity demandValue must be >0 and <=1. The portion applies only to the specified years.

Notes

  • If an entry is specified for one agent and commodity, there must be entries covering all milestone years.
  • For each agent listed in this file, the total portions for each region/commodity/year combination must sum to one.
  • In addition, there must be entries for every SVD and SED commodity for all regions and milestone years.

agent_cost_limits.csv

Limits on expenditure for agents.

FieldDescriptionNotes
agent_idThe agent to apply these values to
yearsThe year(s) to which this entry appliesOne or more milestone years separated by semicolons or all
capex_limitMaximum capital cost the agent will payMust be >0. Optional (defaults to infinity).
annual_cost_limitMaximum annual operating costThe maximum annual operating cost (fuel plus variable operating cost etc.) that the agent will pay. Must be >0. Optional (defaults to infinity).

Notes

  • If cost limits are provided for an agent, they must be present for all years.

agent_objectives.csv

Describes the agents' objectives.

FieldDescriptionNotes
agent_idAn agent ID
yearsThe year(s) to which this entry appliesOne or more milestone years separated by semicolons or all
objective_typeThe type of objectiveMust be npv (net present value) or lcox (levelised cost of X). Note that support for NPV is experimental and may give bad results.
decision_weightWeight for weighted sum decision ruleCurrently unused
decision_lexico_orderOrder in which to consider objectives for lexico decision ruleCurrently unused

Notes

  • Every agent must have one objective for each milestone year.
  • If the weighted sum decision rule is in use, the decision_weight value must be provided, otherwise it must be omitted.
  • If the lexico decision rule is in use, the decision_lexico_order value must be provided, otherwise it must be omitted.

agent_search_space.csv

Defines the processes in which an agent will invest for given parameters.

FieldDescriptionNotes
agent_idAn agent ID
commodity_idThe commodity to which this entry applies
yearsThe year(s) to which this entry appliesOne or more milestone years separated by semicolons or all
search_spaceThe processes in which this agent will investOne or more process IDs separated by semicolons. If this field is empty or all, all processes will be considered.

Notes

  • If entries are missing for any combination of agent, commodity or milestone year, then it is assumed that all processes can be considered in this case.

agents.csv

Describes agents in the system.

FieldDescriptionNotes
idA unique identifier for an agent
descriptionA human-readable label for the agent
regionsThe region(s) in which the agent operatesOne or more region IDs, separated by semicolons or the string all
decision_ruleThe decision rule applied to objectivesCurrently the only supported rule is simple
decision_lexico_toleranceTolerance for lexico decision ruleCurrently unused

Assets

assets.csv

Defines assets in the system.

FieldDescriptionNotes
process_idThe process of which this asset is an instance
region_idThe region in which this agent operates
agent_idThe agent to which this asset belongs
capacityThe capacity of the assetMust be >0
commission_yearThe year in which to commission this assetThis value can be any integer >=0. If it is before the start of the simulation, it will already be commissioned in the first year and if it after the end of the simulation then it will never be commissioned.

Commodities

commodities.csv

Describes commodities in the system.

FieldDescriptionNotes
idA unique identifier for the commodity
descriptionA human-readable label for the commodity
typeThe type of commodityMust be one of svd (service demand), sed (supply equals demand), inc (input commodity) or ouc (output commodity)
time_slice_levelThe time slice level at which constraints for this commodity are appliedMust be one of annual (whole year), season (whole season) or daynight (a particular time of day)

Notes

  • Every SED (supply equals demand) commodity must have both producer and consumer processes for every region and milestone year.
  • Every SVD (service demand) commodity must have a producer for every region and milestone year.

commodity_levies.csv

Defines levies for commodities (or, if value is negative, incentives).

FieldDescriptionNotes
commodity_idThe commodity to which this entry applies
regionsThe region(s) to which this entry appliesOne or more region IDs, separated by semicolons or the string all
yearsThe year(s) to which this entry appliesOne or more milestone years separated by semicolons or all
time_sliceThe time slices(s) to which this entry appliesCan be a single time slice (e.g. winter.day), a whole season (e.g. winter) or annual, representing the whole year
balance_typeThe type of balance to which this is appliedCan be cons (applies to consumption only), prod (applies to production only) or net (applies to consumption and production)
valueThe value of the levy/incentive

Notes

  • If an entry is included for a given combination of commodity and region, entries must be provided covering all milestone years and time slices. For those regions not explicitly included for a given commodity, a zero levy/incentive is assumed. At least one levy/incentive entry must be provided for at least one commodity.

demand.csv

Specifies the demand for service demand commodities.

FieldDescriptionNotes
commodity_idThe service demand commodity to which this entry applies
region_idThe region to which this entry appliesA region ID
yearThe year(s) to which this entry appliesOne or more milestone years separated by semicolons or all
demandTotal demand for this year

Notes

  • Every service demand commodity must have entries in this file covering every combination of milestone year and region.

demand_slicing.csv

Specifies how demand is distributed throughout the year (i.e. for different milestones).

FieldDescriptionNotes
commodity_idThe service demand commodity to which this entry applies
region_idThe region to which this entry appliesA region ID
time_sliceThe time slices(s) to which this entry appliesCan be a single time slice (e.g. winter.day), a whole season (e.g. winter) or annual, representing the whole year
fractionThe fraction of annual demand for this entryMust be >0 and <=1

Notes

  • The user must provide entries covering every combination of service demand commodity, region and time slice.
  • For each combination, the sum of the fractions must equal one.

Processes

process_availabilities.csv

Defines how much of a process's capacity is available throughout the year.

FieldDescriptionNotes
process_idThe process to which this entry applies
regionsThe region(s) to which this entry appliesOne or more region IDs, separated by semicolons or the string all
yearsThe milestone year(s) to which this entry appliesOne or more milestone years separated by semicolons or all
time_sliceThe time slices(s) to which this entry appliesCan be a single time slice (e.g. winter.day), a whole season (e.g. winter) or annual, representing the whole year
limit_typeThe type of limitCan be lo (a lower bound), hi (an upper bound) or fx (indicating that the availability is constant)
valueThe proportion of capacity which is availableMust be >0 and <=1

Notes

  • Must be provided for every process.
  • Only one type of limit can be supplied for each combination of process/region/year/time slice.

process_flows.csv

The commodity flows for each process.

FieldDescriptionNotes
process_idThe process to which this entry applies
commodity_idThe commodity for this flow
regionsThe region(s) to which this entry appliesOne or more region IDs, separated by semicolons or the string all. Must be regions in which the process operates.
yearsThe year(s) to which this entry appliesOne or more milestone years separated by semicolons or all
coeffThe flow for this commodityCan be <0, indicating an input flow, or >0, indicating an output flow. Cannot be zero.
typeThe type of commodity flowCurrently this value must be fixed
costThe cost per unit flowOptional. If present, must be >0.

Notes

  • Commodity flows can vary by region and year.
  • For each process, there must be entries covering all the years and regions in which the process operates.

process_parameters.csv

Parameters for processes which vary by region and year.

FieldDescriptionNotes
process_idThe process to which this entry applies
regionsThe region(s) to which this entry appliesOne or more region IDs, separated by semicolons or the string all. Must be regions in which the process operates.
yearsThe milestone year(s) to which this entry appliesOne or more milestone years separated by semicolons or all
capital_costOvernight capital cost per unit capacity
fixed_operating_costAnnual operating cost per unit capacity
variable_operating_costAnnual variable operating cost per unit activity
lifetimeLifetime in years of an asset created from this processMust be a positive integer
discount_rateProcess-specific discount rateMust be positive. A warning will be issued if this number is >1.
capacity_to_activityFactor for calculating the maximum consumption/production over a year.Must be >=0

Notes

  • For each process, entries must be provided which cover every combination of milestone year and region in which the process operates.

processes.csv

Describes processes in the system.

FieldDescriptionNotes
idA unique identifier for a process
descriptionA human-readable label for the process
regionsThe region(s) in which this process can operateOne or more region IDs, separated by semicolons or the string all
primary_outputThe primary output commodity, if any, for this processThis field must be omitted for processes with only input flows. It can be omitted if there is only one output flow, in which can it will be inferred.
start_yearThe first year when this process is available to agents
end_yearThe last year when this process is available to agentsMust be >= to start_year

Output Files

This file contains information about the file formats for MUSE 2.0 output files.

Note that we only document the main CSV output files, not those produced when the --debug-model option is active.

Metadata: metadata.toml

Metadata about the program run, the MUSE 2.0 build and the user's platform.

Top-level table

FieldDescriptionNotes
runInformation about the program run
programInformation about MUSE 2.0
platformInformation about the platform on which the simulation was run

[run] table

FieldDescriptionNotes
model_pathPath to the input model
datetimeTimestamp for the model runTime at which the model run commenced

[program] table

FieldDescriptionNotes
nameThe name of the program (muse2)
versionProgram version (e.g. 2.0.0)
targetThe target triple MUSE 2.0 was built for
is_debugWhether the current build is a debug or release build
rustc_versionThe version of rustc used to compile MUSE 2.0
build_time_utcThe UTC time and date at which MUSE 2.0 was built
git_commit_hashThe short hash of the git commit from which MUSE 2.0 was builtIf the git working tree was dirty, -dirty is appended to the hash

[platform] table

FieldDescriptionNotes
sysnameThe name of the implementation of the operating system
nodenameThe hostname of the machine
releaseThe release level of the operating system
versionThe version level of the release
machineThe name of the system's hardware
osnameThe name of the current OS

Main CSV output files

assets.csv

Assets commissioned during the course of the simulation.

FieldDescriptionNotes
asset_idThe ID number of this assetEvery commissioned asset in the system is automatically assigned a numerical ID. This includes assets supplied by the user in the assets.csv input file as well as those selected by agents during the simulation.
process_idThe ID of this asset's associated process
region_idThe region in which this asset exists
agent_idThe agent to which this asset belongs
commission_yearThe year in which the asset was commissioned
decommission_yearThe year in which the asset was decommissionedThis field will be empty if the asset was not decommissioned during the lifetime of the simulation
capacityThe capacity of the asset

commodity_flows.csv

How much of each commodity was produced and consumed in the course of the simulation.

FieldDescriptionNotes
milestone_yearMilestone year of the simulation
asset_idThe asset this entry relates toSee the assets.csv output file for information about assets
commodity_idThe commodity this entry relates to
time_sliceThe time slice during which this flow occurred
flowThe amount of commodity flowIf the commodity was produced, this value will be positive and if it was consumed, it will be negative.

commodity_prices.csv

The prices of commodities over time and place.

FieldDescriptionNotes
milestone_yearMilestone year of the simulation
commodity_idThe commodity this entry relates to
region_idThe region this entry relates to
time_sliceThe time slice in which this price holds
priceThe price of the commodity

Model Description

The purpose of MUSE 2.0 (ModUlar energy systems Simulation Environment) is to provide users with a framework to simulate pathways of energy system transition, usually in the context of climate change mitigation.

Model Concept

MUSE 2.0 is a bottom-up engineering-economic modelling framework that computes a price-induced supply-demand equilibrium on a set of user-defined commodities. It does this for each milestone time period within a user-defined time horizon. This is a "partial equilibrium" in the sense that the framework equilibrates only the user-defined commodities, as opposed to a whole economy.

MUSE 2.0 is data-driven in the sense that model processing and data are entirely independent, and user-defined data is at the heart of how the model behaves. It is also "bottom-up" in nature, which means that it requires users to characterise each individual process that produces or consumes each commodity, along with a range of other physical, economic and agent parameters.

At a high level, the user defines:

  1. The overall temporal arrangements, including the base time period, milestone time periods and time horizon, and within-period time slice lengths.

  2. The service demands for each end-use (e.g. residential heating, steel production), for each region, and how that demand is distributed between the user-defined time slices within the year. Service demands must be given a value for the base time period and all milestone time periods in each region.

  3. The existing capacity of each process (i.e. assets) in the base time period, and the year in which it was commissioned or will be decommissioned.

  4. The techno-economic attributes (e.g. capital cost, operating costs, efficiency, lifetime, input and output commodities, etc) of each process. This must include attributes of processes existing in the base time period (i.e. assets) and possible future processes that could be adopted in future milestone time periods.

  5. The agents that choose between processes by applying search spaces, objectives and decision rules. Portions of demand for each commodity must be assigned to an agent, and the sum of these portions must be one.

Framework Overview

The model framework is designed to operate sequentially across several distinct milestone years (MSY). For each MSY, it endogenously determines asset decommissioning (both scheduled and economically-driven) and guides new capacity investments. The overarching objective is to simulate agent decision-making to serve commodity (and service) demand.

A fundamental premise for the investment appraisal is that prices for balanced commodities (Supply Equals Demand: SED) from the previous milestone year (\( \pi_{prevMSY} \)) are considered reliable for economic evaluations. Service demand commodity (SVD) prices from \( MSY_{prev} \) may or may not be reliable (as defined by the user), guiding the choice of appraisal method for assets producing them. It is designed as a recursive dynamic model with imperfect foresight.

The workflow is structured as follows:

  1. Dispatch is executed for a calibrated base year. Dispatch is executed using the formulation shown in Dispatch Optimisation Formulation. All existing assets are included, and all candidate assets for the \( MSY_{next} \) are included with capacities set to zero. This ensures that all commodity shadow prices and reduced costs for candidate asset are generated for use in the \( MSY_{next} \). \( VoLL \) load shedding variables should be zero after completion, and if they are non-zero then throw an error as the model is not properly calibrated.

  2. Time-travel loop: Move to the next milestone year (\( MSY \)).

    1. Decommission assets that reached their end of life. This establishes the existing asset fleet for the current \( MSY \) by accounting for initial retirements. \( ExistingCapacity \) is the set of existing assets and their capacities available after EOL decommissioning.

    2. Determine SVD demand profiles and run investment appraisal tools for them. SVD demand profiles for the \( MSY \) are determined from user input data. The investment appraisal tools are applied to determine portfolios of existing and new assets to meet demand for each SVD commodity. Prices of input commodities are known from the final dispatch of the previous milestone year. This finalises \( NewCapacity \) and \( AssetChosen \) for each SVD.

    3. Build System Layer-by-Layer loop: Completes the investment pass for the milestone year, progressively adding commodities layer by layer. This step determines new asset capacities (\( NewCapacity \)) and selects existing assets that remain competitive (\( AssetChosen \)). Other existing assets are decommissioned if they are not utilised for \( MothballYears \) years (a user-input asset parameter). This inner loop continues until no different SED commodities (that have not been processed using the investment appraisal tools) are added as commodities of interest for this iteration.

      1. Determine the commodities of interest for investment. In the base year this is all service demand (SVD) commodities. After the base year, the commodities of interest are determined dynamically; they are the set of commodities that are consumed by the assets invested/chosen in the last iteration (layer) of this loop.

      2. Dispatch to determine commodity of interest demand profile. Dispatch is executed using the formulation shown in Dispatch Optimisation Formulation, but only including system elements downstream of the commodities of interest. Commodity prices for upstream/unknown inputs/outputs from assets serving the commodities of interest and assets downstream of the commodities of interest with unknown commodity prices (if any) are assumed to take on commodity prices from the previous MSY. Care must be taken to avoid any double-counting of prices and e.g. commodity levies. Demand profiles for commodities of interest are recorded (\( D[c,r,t] \)).

      3. Run investment appraisal tools for each commodity of interest. The investment appraisal tools are applied to determine portfolios of existing and new assets to meet demand for each commodity of interest. It is necessary to consider the complete demand profile of each commodity of interest, as even where demand can be served with existing assets in the MSY without new investment, economic decommissioning is still possible.

      4. Finalise new capacity and retained assets that produce the commodities of interest. \( NewCapacity \) and \( AssetChosen \) are finalised for the layer.

      5. Check if there are SED commodities that the investment appraisal tools have not been run for. If yes, move to next layer of the layering loop at step 2(c). If no, layering loop ends, break and continue at step 2(d).

    4. Ironing-out loop, with iteration limit \( k_{max} \). For each \( k \):

      1. Execute dispatch as per Dispatch Optimisation Formulation with the complete system, with all candidate assets for the \( MSY_{next} \) included with capacities set to zero to generate prices and reduced costs for the \( MSY_{next} \).

      2. Check if load-weighted average prices for any SED commodity has changed (or changed more than a tolerance) since the last loop (also, possibly check if the 95th percentile of price has changed more than a tolerance). If yes, continue at 2(d)iii. If no, this MSY is complete, and if further MSY exist continue time-travel loop from step 2, or if no further MSY exist then go to step 3.

      3. If \( k = k_{max} \) break with a warning telling the user that this loop did not converge, identifying out-of-balance commodities. If further MSY exist continue time-travel loop from step 2, or if no further MSY exist then go to step 3.

      4. Re-run investment appraisal tools for the assets and commodities that are contributing to the price instability.

  3. Outer loop ends when no further milestone years exist.

Dispatch Optimisation Formulation

This dispatch optimisation model calculates the least-cost operation of the energy system for a given configuration of assets and capacities, subject to demands and constraints. It is the core engine used for each dispatch run referenced in the overall MUSE 2.0 workflow. A key general assumption is that SVD commodities represent final demands only and are not consumed as inputs by any asset.

General Sets

These define the fundamental categories used to define the energy system.

  • \( \mathbf{R} \): Set of Regions (indexed by \( r \)). Represents distinct geographical or modelling areas.

  • \( \mathbf{T} \): Set of Time Slices (indexed by \( t \)). Discrete operational periods within a year.

  • \( \mathbf{H} \): Set of Seasons (indexed by \( h \)). Collections of time slices.

  • \( \mathbf{A} \): Set of All Assets (indexed by \( a \)). All existing and candidate production, consumption, or conversion technologies.

  • \( \mathbf{A}^{flex} \subseteq \mathbf{A} \): Subset of Flexible Assets (variable input/output ratios).

  • \( \mathbf{A}^{std} = \mathbf{A} \setminus \mathbf{A}^{flex} \): Subset of Standard Assets (fixed input/output coefficients).

  • \( \mathbf{C} \): Set of Commodities (indexed by \( c \)). All energy carriers, materials, or tracked flows. Partitioned into:

    • \( \mathbf{C}^{\mathrm{SVD}} \): Supply-Driven Commodities (final demands; not consumed by assets).

    • \( \mathbf{C}^{\mathrm{SED}} \): Supply-Equals-Demand Commodities (intermediate system flows like grid electricity).

    • \( \mathbf{C}^{\mathrm{OTH}} \): Other Tracked Flows (e.g., losses, raw emissions).

  • \( \mathbf{C}^{VoLL} \subseteq \mathbf{C}^{\mathrm{SVD}} \cup \mathbf{C}^{\mathrm{SED}} \): Subset of commodities where unserved demand is modelled with a penalty.

  • \( \mathbf{P} \): Set of External Pools/Markets (indexed by \( p \)).

  • \( \mathbf{S} \): Set of Scopes (indexed by \( s \)). Sets of \( (r,t) \) pairs for policy application.

A. Core Model (Standard Assets: \( a \in \mathbf{A}^{std} \))

Purpose: Defines the operation of assets with fixed, predefined input-output relationships.

A.1. Parameters (for \( a \in \mathbf{A}^{std} \) or global)

  • \( duration[t] \): Duration of time slice \( t \) as a fraction of the year (\( \in (0,1] \)). Represents the portion of the year covered by this slice.

  • \( season\_ slice[h,t] \): Binary indicator; \( 1 \) if time slice \( t \) is in season \( h \), \( 0 \) otherwise. Facilitates seasonal aggregation.

  • \( balance\_ level[c,r] \): Defines the temporal resolution (’timeslice’, ’seasonal’, ’annual’) at which the supply-demand balance for commodity \( c \) in region \( r \) must be enforced.

  • \( demand[r,c] \): Total annual exogenously specified demand (\( \ge 0 \)) for commodity \( c \in \mathbf{C}^{\mathrm{SVD}} \) in region \( r \). This is the final demand to be met.

  • \( timeslice\_ share[c,t] \): Fraction (\( \in [0,1] \)) of the annual \( demand[r,c] \) for \( c \in \mathbf{C}^{\mathrm{SVD}} \) that occurs during time slice \( t \). (\( \sum_{t}timeslice\_ share[c,t]=1 \)). Defines the demand profile.

  • \( capacity[a,r] \): Installed operational capacity (\( \ge 0 \)) of asset \( a \) in region \( r \) (e.g., MW for power plants). This value is an input to each dispatch run.

  • \( cap2act[a] \): Conversion factor (\( >0 \)) from asset capacity units to activity units, ensuring consistency between capacity (e.g., MW) and activity (e.g., MWh produced in a slice) considering \( duration[t] \).

  • \( avail_{UB}[a,r,t], avail_{LB}[a,r,t], avail_{EQ}[a,r,t] \): Availability factors (\( \in [0,1] \)) for asset \( a \) in time slice \( t \). \( UB \) is maximum availability, \( LB \) is minimum operational level, \( EQ \) specifies exact operation if required.

  • \( cost_{var}[a,r,t] \): Variable operating cost (\( \ge 0 \)) per unit of activity for asset \( a \) (e.g., non-fuel O&M).

  • \( input_{coeff}[a,c] \): Units (\( \ge 0 \)) of commodity \( c \in (\mathbf{C}^{\mathrm{SED}} \cup \mathbf{C}^{\mathrm{OTH}}) \) consumed by asset \( a \) per unit of its activity. (By assumption, \( input_{coeff}[a,c]=0 \) if \( c \in \mathbf{C}^{\mathrm{SVD}} \)).

  • \( output_{coeff}[a,c] \): Units (\( \ge 0 \)) of commodity \( c \in \mathbf{C} \) produced by asset \( a \) per unit of its activity.

  • \( cost_{input}[a,c] \): Specific cost (\( \ge 0 \)) per unit of input commodity \( c \) consumed by asset \( a \). Useful if \( c \) attracts a levy/incentive \( only \) if it is consumed by this type of asset.

  • \( cost_{output}[a,c] \): Specific cost (if positive) or revenue (if negative) per unit of output commodity \( c \) produced by asset \( a \). Useful if levy/incentive applies \( only \) when the commodity is produced by this type of asset.

  • \( VoLL[c,r] \): Value of Lost Load. A very high penalty cost applied per unit of unserved demand for \( c \in \mathbf{C}^{VoLL} \) in region \( r \).

A.2. Decision Variables

These are the quantities the dispatch optimisation model determines.

  • \( act[a,r,t]\ge0 \): Activity level of asset \( a \) in region \( r \) during time slice \( t \). This is the primary operational decision for each asset.

  • \( UnmetD[c,r,t]\ge0 \): Unserved demand for commodity \( c \in \mathbf{C}^{VoLL} \) in region \( r \) during time slice \( t \). This variable allows the model to find a solution even if capacity is insufficient.

A.3. Objective Contribution (for standard assets \( a \in \mathbf{A}^{std} \))

This term represents the sum of operational costs associated with standard assets, forming a component of the overall system cost that the model seeks to minimise.

\[ \sum_{a\in \mathbf{A}^{std}}\sum_{r,t} act[a,r,t] \Biggl( cost_{var}[a,r,t] + \sum_{c \notin \mathbf{C}^{\mathrm{SVD}}} cost_{input}[a,c]\,input_{coeff}[a,c] + \sum_{c \in \mathbf{C}} cost_{output}[a,c]\,output_{coeff}[a,c] \Biggr) \]

A.4. Constraints (Capacity & Availability for standard assets \( a \in \mathbf{A}^{std} \))

These constraints ensure that each standard asset’s operation respects its physical capacity and time-varying availability limits. For all \( a \in \mathbf{A}^{std}, r, t \):

  • Asset activity \( act[a,r,t] \) is constrained by its available capacity, considering its minimum operational level (lower bound, LB) and maximum availability (upper bound, UB):

    \[ \begin{aligned} capacity[a,r]\,cap2act[a]\,avail_{LB}[a,t]\,duration[t] &\le act[a,r,t] \\ act[a,r,t] &\le capacity[a,r]\,cap2act[a]\,avail_{UB}[a,t]\,duration[t] \end{aligned} \]

  • If an exact operational level is mandated (e.g., for some renewables based on forecast, or fixed generation profiles for specific assets):

    \[ act[a,r,t] = capacity[a,r]\,cap2act[a]\,avail_{EQ}[a,t]\,duration[t] \]

B. Full Model Construction

Note: This section includes references to many features that are not described elsewhere in this document or implemented yet (e.g. region-to-region trade), but these are included for completeness. This represents the roadmap for future MUSE 2.0 development.

This section describes how all preceding components are integrated to form the complete dispatch optimisation problem. 1. Sets, Parameters, Decision Variables: The union of all previously defined elements. 2. Objective Function: The overall objective is to minimise the total system cost, which is the sum of all operational costs from assets (standard and flexible), financial impacts from policy scopes (taxes minus credits), costs of inter-regional trade, costs of pool-based trade, and importantly, the high economic penalties associated with any unserved demand for critical commodities:

\[ \begin{aligned} \text{Minimise: } &(\text{Core Asset Operational Costs from A.3 and E.4}) \\ &+ (\text{Scope Policy Costs/Credits from B.4}) \\ &+ (\text{Region-to-Region Trade Costs from C.4}) + (\text{Pool-Based Trade Costs from D.4}) \\ &+ \sum_{c \in \mathbf{C}^{VoLL},r,t} UnmetD[c,r,t] \cdot VoLL[c,r] \quad \text{(Penalty for Unserved Demand)} \end{aligned} \]

Constraints

The complete set of constraints that the optimisation must satisfy includes:

  • Capacity & Availability constraints for all assets \( a \in \mathbf{A} \) (as per A.4 and E.5).

  • Scope policy constraints (B.5).

  • Region-to-Region Trade Limits (C.5.A).

  • Pool-Based Trade Limits (D.5.A).

  • Flexible Asset operational constraints (E.5).

Demand Satisfaction for \( c\in \mathbf{C}^{\mathrm{SVD}} \)

These constraints ensure that exogenously defined final demands for SVDs are met in each region \( r \) and time slice \( t \), or any shortfall is explicitly accounted for.

For all \( r,t,c \in \mathbf{C}^{\mathrm{SVD}} \): Let \( TotalSystemProduction_{SVD}[c,r,t] \) be the sum of all production of \( c \) from standard assets (\( output_{coeff}[a,c]\,act[a,r,t] \)) and flexible assets (the relevant \( OutputSpec[a,c,r,t] \) if \( c \in \mathbf{C}_a^{eff\_out} \), or \( act[a,r,t] \cdot coeff_{aux\_out}[a,c] \) if \( c \in \mathbf{C}^{aux\_out}_a \)).

Let \( NetImports_{SVD}[c,r,t] \) be net imports of \( c \) from R2R and Pool trade if SVDs are tradeable. If \( c \in \mathbf{C}^{VoLL} \) (meaning unserved demand for this SVD is permitted at a penalty):

\[ TotalSystemProduction_{SVD}[c,r,t] + NetImports_{SVD}[c,r,t] + UnmetD[c,r,t] = demand[r,c] \times timeslice\_ share[c,t] \]

Else (if SVD \( c \) must be strictly met and is not included in \( \mathbf{C}^{VoLL} \)):

\[ TotalSystemProduction_{SVD}[c,r,t] + NetImports_{SVD}[c,r,t] = demand[r,c] \times timeslice\_ share[c,t] \]

Commodity Balance for \( c\in \mathbf{C}^{\mathrm{SED}} \)

These constraints ensure that for all intermediate SED commodities, total supply equals total demand within each region \( r \) and for each balancing period defined by \( balance\_ level[c,r] \) (e.g., timeslice, seasonal, annual).

For a timeslice balance (\( \forall r,t,c \in \mathbf{C}^{\mathrm{SED}} \)):

Total Inflows (Local Production by all assets + Imports from other regions and pools + Unserved SED if \( c \in \mathbf{C}^{VoLL} \)) = Total Outflows (Local Consumption by all assets + Exports to other regions).

\[ \begin{aligned} &\sum_{a \in \mathbf{A}^{std}} output_{coeff}[a,c]\,act[a,r,t] && \text{(Std Asset Production)} \\ &+ \sum_{a \in \mathbf{A}^{flex}} \left( \begin{cases} OutputSpec[a,c,r,t] & \text{if } c \in \mathbf{C}^{eff\_out}_a \\ act[a,r,t] \cdot coeff_{aux\_out}[a,c] & \text{if } c \in \mathbf{C}^{aux_out}_a \ 0 & \text{otherwise} \end{cases} \right) && \text{(Flex Asset Production)} \\ &+ \sum_{r'\neq r, c \in \mathbf{C}^R} ship_{R2R}[r',r,c,t](1 - loss_{R2R}[r',r,c,t]) && \text{(R2R Imports)} \\ &+ \sum_{p, c \in \mathbf{C}^P} ship_{pool}[p,r,c,t](1 - loss_{pool}[p,r,c,t]) && \text{(Pool Imports)} \\ &+ \mathbb{I}(c \in \mathbf{C}^{VoLL}) \cdot UnmetD[c,r,t] && \text{(Unserved SED, if modelled)} \\ &= \sum_{a \in \mathbf{A}^{std}} input_{coeff}[a,c]\,act[a,r,t] && \text{(Std Asset Consumption)} \\ &+ \sum_{a \in \mathbf{A}^{flex}} \left( \begin{cases} InputSpec[a,c,r,t] & \text{if } c \in \mathbf{C}^{eff\_in}_a \\ act[a,r,t] \cdot coeff_{aux\_in}[a,c] & \text{if } c \in \mathbf{C}^{aux\_in}_a \\ 0 & \text{otherwise} \end{cases} \right) && \text{(Flex Asset Consumption)} \\ &+ \sum_{r'\neq r, c \in \mathbf{C}^R} ship_{R2R}[r,r',c,t] && \text{(R2R Exports)} \end{aligned} \]

(where \( \mathbb{I}(c \in \mathbf{C}^{VoLL}) \) is an indicator function, \( 1 \) if \( c \) is in \( \mathbf{C}^{VoLL} \), \( 0 \) otherwise. Note that SVDs are not consumed by assets, so \( input_{coeff}[a,c] \) and related terms for SVDs on the consumption side are zero).

Investment Appraisal Approach

This section details the investment and asset retention decision process, which is applied within step 2 of the overall MUSE 2.0 workflow. This process determines which new assets to build and which existing assets to retain to meet system needs over time. In the overall workflow, dispatch optimisation is used to identify physical needs by quantifying demand profiles for commodities of interest.

The economic evaluation and selection of all supply options—new candidate assets (\( ca \)) and contributions from existing assets (\( ex \))—consistently use prices formed in the previous milestone year (\( \pi_{prevMSY} \)). This approach models investment and retention decisions as being based on recent, known economic conditions while responding to immediate commodity demands. A core assumption is that all commodities, except specific user-identified SVD commodities, have reliable \( \pi_{prevMSY} \) values for these economic evaluations.

Data for economic evaluation of supply options

This data provides the primary economic context for appraisal calculations, drawn from the settled state of the preceding milestone year.

  • Previous MSY prices: \( \pi_{prevMSY}[c,r,t] \). When pricing_strategy is shadow_prices, these are the shadow prices for each commodity \( c \), in each region \( r \), for each time slice \( t \), taken from the final dispatch of the preceding MSY. When the pricing_strategy option is set to scarcity_adjusted, these are the shadow prices for each commodity adjusted to remove the impact of binding capacity constraints.

  • Previous MSY reduced costs for new candidates: \( rc_{prevMSY}[ca,r,t] \). If candidate assets \( ca \) were included (at zero capacity) in the \( \text{MSY}_{prev} \)’s final dispatch run, their reduced costs were generated and can be used as a measure of their profitability in \( \text{MSY}_{next} \).

Candidate and existing asset data

Asset economic data for investment appraisal calculations, drawn from user inputs and previous investments.

  • For all assets:

    • All relevant operational parameters for \( opt \) as defined in Dispatch Optimisation Formulation (e.g., availability \( avail_{UB} \), variable costs \( cost_{var} \), yield coefficients \( output_{coeff} \), etc.).

    • \( \text{FOM}_{opt,r} \): Annual fixed Operations & Maintenance costs per unit of capacity for \( opt \) in \( r \).

    • \( FinancingInDecomDec_{ex} \) (binary flag). This user-defined option specifies whether to include estimated financing costs in the economic viability threshold when considering the decommissioning of an existing asset. This can only be used on profit-evaluable assets. Used with \( PercentDebt_{ex} \). Where financing costs are included, the percentage debt is multiplied by the original capex, and the result is annualised.

  • For new candidate assets:

    • \( \text{CAPEX}_{ca,r} \): Upfront capital expenditure required per unit of new capacity for candidate \( ca \) in region \( r \).

    • \( \text{Life}_{ca} \): Expected operational lifetime of the new asset \( ca \) (in years).

    • \( \text{WACC}_{ca} \): Weighted Average Cost of Capital (discount rate) used for appraising candidate \( ca \).

    • \( CapMaxBuild_{ca,r} \): Maximum buildable new capacity for candidate asset type \( ca \) in region \( r \) during this MSY investment phase (an exogenous physical, resource, or policy limit).

Investment Appraisal

The main MUSE 2.0 workflow invokes the portfolio construction methods detailed in tools A and B below. These tools select the best asset from the pool of candidate and existing assets, thereby providing investment and dynamic decommissioning decisions.

Pre-calculation of metrics for each supply option

Note: This section contains a reference to "scopes", a feature that is not yet implemented

  • Annualised fixed costs per unit of capacity (\( AFC_{opt,r} \)): For new candidates, this is their annualised CAPEX plus FOM. For existing assets, the relevant fixed cost is its FOM.

  • Determine candidate asset reduced cost or equivalent for existing assets: For candidate assets, if pricing_strategy is scarcity_adjusted, candidate asset reduced costs are as provided by the solver. If pricing_strategy is shadow_prices, candidate asset reduced costs must be calculated as follows:

    \[ \begin{aligned} RC^*_{ca,r,t} = RC_{ca,r,t} &- \sum_{c} \Big( input_{\text{coeff}}[ca,c] - output_{\text{coeff}}[ca,c] \Big) \cdot \lambda_{c,r,t} \\ &+ \sum_{c} \Big( input_{\text{coeff}}[ca,c] - output_{\text{coeff}}[ca,c] \Big) \cdot \lambda^*_{c,r,t} \end{aligned} \]

    Where \( RC^*_{ca,r,t} \) is the adjusted reduced cost, \( RC_{ca,r,t} \) is the solver-provided reduced cost, \( \lambda_{c,r,t} \) is the solver-provided commodity shadow price, and \( \lambda^*_{c,r,t} \) is the adjusted commodity price (which removes the impact of scarcity pricing).

    For existing assets, an equivalent to reduced cost is calculated as follows:

    \[ \begin{aligned} RC^*_{ex,r,t} = & \quad cost_{\text{var}}[ex,r,t] \\ &+ \sum_{c} \Big( cost_{\text{input}}[ex,c] \cdot input_{\text{coeff}}[ex,c] + cost_{\text{output}}[ex,c] \cdot output_{\text{coeff}}[ex,c] \Big) \\ &+ \sum_{c} \Big( input_{\text{coeff}}[ex,c] - output_{\text{coeff}}[ex,c] \Big) \cdot \lambda^*_{c,r,t} \\ &+ \sum_{s,c} in\_scope[s] \cdot \Big\{ \\ &\quad \quad (cost_{\text{prod}}[s,c] - \mu_{s,c}^{\text{prod}}) \cdot output_{\text{coeff}}[ex,c] \\ &\quad \quad + (cost_{\text{cons}}[s,c] - \mu_{s,c}^{\text{cons}}) \cdot input_{\text{coeff}}[ex,c] \\ &\quad \quad + (cost_{\text{net}}[s,c] - \mu_{s,c}^{\text{net}}) \cdot (output_{\text{coeff}}[ex,c] - input_{\text{coeff}}[ex,c]) \\ &\Big\} \end{aligned} \]

    Where \( RC^*_{ex,r,t} \) is the marginal surplus, \( \lambda^*_{c,r,t} \) is the adjusted commodity price (which removes the impact of scarcity pricing) or the solver-provided shadow price (including scarcity pricing) as appropriate.

    For the case of LCOX objective, \( RC^*_{ex,r,t} \) must also be adjusted to remove the prices of non-priced commodities, and the price of the commodity of interest. For these commodities \( \lambda^*_{c,r,t} \) and \( \lambda_{c,r,t} \) are set to zero, and \( RC^*_{ex,r,t} \) adjusted as a result.

Initialise demand profiles for commodity of interest

  • Initialise \( D[c,t] \) from the MSY dispatch run output \( U_c \).

  • We break down the demand profile into tranches. The first tranche for investment consideration is that with the highest load factor. The size of this tranche is the overall peak demand divided by an input parameter (which can vary between 2 and 6). This assumption should be revisited!

Iteratively construct asset portfolio to meet target \( U_c \)

Note: The current implementation of MUSE 2.0 doesn't use tranches

  1. Start with the first tranche of the demand.

  2. Loop over available options \( opt \) (new or existing or import), applying either tool A or B to check the supply option.

  3. Result includes all options \( opt^* \) (new or existing or import) from which we select the one that is the best. The related capacity to commit is returned from the tool, as is its production profile related to the tranche. Save key information, including investment/retention metric for all options, even the ones not invested/retained.

  4. \( D[c] \) is updated to remove the production profile of the committed asset. The next tranche profile is then calculated (note that \( opt^* \) may not serve all demand in the current tranche).

  5. Keep going until there is no \( D[c] \) left. Will need to handle a situation where we run out of candidate and existing assets and demand is still present.

Tools

Tool A: NPV

This method is used when decision rule is single objective and objective is annualised profit for agents’ serving commodity \( c \). This method iteratively builds a supply portfolio by selecting options that offer the highest annualised profit for serving the current commodity demand. The economic evaluation uses \( \pi_{prevMSY} \) prices and takes account of asset-specific operational constraints (e.g., minimum load levels) and the balance level of the target commodity (time slice profile, seasonal or annual).

  • Choose capacity and dispatch to maximise annualised profit: Solve a small optimisation sub-problem to maximise the asset’s surplus, subject to its operational rules and the specific demand tranche it is being asked to serve. Define \( SurplusPerAct_{opt,t} = - RC^*_{opt,r,t} \).

    \[ maximise \Big\{ -AFC_{opt,r}*cap_{opt,r} + \sum_{t} act_{opt,t}*SurplusPerAct_{opt,t} \Big\} \]

    Where \( cap_{opt,r} \) and \( act_{opt,t} \) are decision variables, and subject to:

    • The asset operational constraints (e.g., \( avail_{LB}, avail_{EQ} \), etc.), activity less than capacity, applied to its activity profile \( act_{opt,t} \).

    • A demand constraint, where output cannot exceed demand in the tranche, which adapts based on the commodity’s balance level (time slice, season, annual).

    • Capacity is constrained \( <CapMaxBuild_{opt,r} \) for candidates, and to known capacity for existing assets.

  • Calculate a profitability index: This is the total annualised surplus (\( \sum_{t} act_{opt,t}*SurplusPerAct_{opt,t} \)) divided by the annualised capital cost (\( AFC_{opt,r}*cap_{opt,r} \)).

  • Save information: Save \( opt \) information. If this is the last \( opt \) then exit this loop.

Tool B: LCOX

This method is used when decision rule is single objective and objective is LCOX for agents’ serving commodity \( c \). This method constructs a supply portfolio (from new candidates \( ca \), new import infrastructure \( ca_{import} \), and available existing assets \( ex \)) to meet target \( U_{c} \) at the lowest cost for the investor. As above, the appraisal for each option explicitly accounts for its own operational constraints and adapts based on the \( balance_level \) of \( c \). Inputs and outputs for all options are valued using prices from the previous milestone year (\( \pi_{prevMSY} \)), for priced commodities. Inputs and outputs for unpriced commodities are set to zero, and the commodity of interest is assumed to have zero value.

  • Choose capacity and dispatch to minimise annualised cost: Solve a small optimisation sub-problem to maximise the asset’s surplus, subject to its operational rules and the specific demand tranche it is being asked to serve. Define \( CostPerAct_{opt,t} = RC^*_{opt,r,t} \).

    \[ minimise \Big\{ AFC_{opt,r}*cap_{opt,r} + \sum_{t} act_{opt,t}*CostPerAct_{opt,t} + VoLL*UnmetD_{r,c,t} \Big\} \]

    Where \( cap_{opt,r} \) and \( act_{opt,t} \) are decision variables, and subject to:

    • The asset operational constraints (e.g., \( avail_{LB}, avail_{EQ} \), etc.), activity less than capacity, applied to its activity profile \( act_{opt,t} \).

    • A demand constraint, where output from the asset plus VoLL-related outputs must equal demand in each timeslice of the tranche, which adapts based on the commodity’s balance level (time slice, season, annual).

    • Capacity is constrained \( <CapMaxBuild_{opt,r} \) for candidates, and to known capacity for existing assets.

    • VoLL variables are active to ensure a feasible solution alongside maximum operation of the asset.

  • Calculate a cost index: This is the total annualised cost (\( AFC_{opt,r}*cap_{opt,r}+\sum_{t} act_{opt,t}*CostPerAct_{opt,t} \)), divided by the annual output \( \sum_{t} act_{opt,t} \).

  • Save information: Save \( opt \) information. If this is the last \( opt \) then exit this loop.

Model diagrams

This document contains diagrams showing the algorithm used by MUSE 2.0. It is likely to contain errors and omissions and will change as the code is developed. It is principally aimed at MUSE developers.

Functions are described with the following terms:

  • Inputs: immutable input arguments; values not modified by function
  • Outputs: values returned from function
  • Modifies: mutable input arguments; values modified by function

Overview of MUSE 2.0
Figure 1: Overview of MUSE 2.0 algorithm

Dispatch optimisation
Figure 2: Overview of dispatch optimisation

Glossary

Activity: The flow of input/s or output/s of a Process that are limited by its capacity. For example, a 500MW power station can output 500MWh per hour of electrical power, or a 50MW electrolyser consumes up to 50MWh per hour of electrical power to produce hydrogen.

Agent: A decision-making entity in the system. An Agent is responsible for serving a user-specified portion of a Commodity demand or Service Demand. Agents invest in and operate Assets to serve demands and produce commodities.

Agent Objective/s: One or more objectives that an Agent considers when deciding which Process to invest in. Objectives can be economic, environmental, or others.

Asset: Once an Agent makes an investment, the related capacity of their chosen Process becomes an Asset that they own and operate. An Asset is an instance of a Process, it has a specific capacity, and a decommissioning year. A set of Assets must exist in the base year sufficient to serve base year demands (i.e. a calibrated base year, based on user input data).

Availability: The maximum, minimum or fixed percentage of maximum output (or input) that an Process delivers over a period. The time period could be a single time slice, a season, or a year.

Base Year: The starting year of a model run. The base year is typically calibrated to known data, including Process stock and commodity consumption/production.

Calibration: The act of ensuring that the model represents the system being modelled in a historical base year.

Capacity: The maximum output (or input) of an Asset.

Capital Cost: The overnight capital cost of a process.

Commodity: A substance (e.g. CO2) or form of energy (e.g. electricity) that can be produced and/or consumed by Processes* in the model. A Service Demand is a type of commodity that is defined at the end point of the system.

Commodity Levy: Represents a tax, levy or other external cost on a commodity. Levies can be applied to all commodity production (sum of output of all processes for that commodity), net production (sum of output and input for all processes), or all consumption (sum of input for all processes). It can also be negative, indicating an incentive on commodity production/consumption/net.

Decision Rule: The rule via which an Agent uses the Objective/s to decide between Process options to invest in. Examples include single objective, weighted sum between multiple objectives, or epsilon constraint where a secondary objective is considered if two options with similar primary objectives are identified.

Dispatch: The way in which Assets are operated to serve demand. MUSE 2.0 uses merit order dispatch, subject to Availability and other constraints that can be defined by the user.

End Year: The final year in the model time horizon.

Equivalent Annual Cost (EAC): An Agent objective, representing the annualised cost of serving all or part of an Agent's demand for a year, considering the Asset's entire lifetime.

Fixed Operating Cost: The Asset or Process annual operating cost charged per unit of capacity.

Input Commodity/ies: The commodities that flow into a Process.

Levelised Cost of X (LCOX): An Agent objective, representing the discounted cost of 1 unit of output commodity X from a process over its lifetime under a specified discount rate.

Lifetime: The lifetime of a Process, measured in years.

Milestone Years: A set of years in the model time horizon where model results are recorded. For example, with a 2025 Base Year and End Year 2100, a user might choose to record outputs in 5-year steps.

Merit Order: A method of operating Assets when the cheapest is dispatched first, followed by the next most expensive, etc, until demand is served. Also called “unit commitment.”

Output Commodity/ies: The commodities that flow out of a Process.

Process: A blueprint of an available Process that converts input commodities to output commodities. Processes have economic attributes of capital cost, fixed operating cost per unit capacity, non-fuel variable operating cost per unit activity, and risk discount rate. They have physical attributes of quantity and type of input and output commodities (which implicitly specify efficiency), Availability limits (by time slice, season and/or year), lifetime (years). When a Process is selected by an Agent for investment an instance of it called an Asset is created.

Region: A geographical area that is modelled. Regions primarily determine trade boundaries.

Season: A year is usually broken down into seasons in the model. For example, summer, winter, other.

Sector: Models are often broken down into sectors, each of which is associated with specific Service Demands or specific Commodity production. For example, the residential sector, the power sector, etc.

Service Demand: A Service Demand is a type of commodity that is consumed at the boundary of the modelled system. For example, tonne-kilometers of road freight, PJ of useful heat demand, etc.

Discount Rate: The discount rate used to calculate any process-specific agent economic objectives that require a discount rate. For example, Equivalent Annual Cost, Net Present Value, Levelised Cost of X, etc.

Time Horizon: The overall period modelled. For example, 2025–2100.

Time Period: Refers to a specific Milestone Year in the time horizon.

Time Slice: The finest time period in the model. The maximum time slice length is 1 year (where a model does not represent seasons or within-day (diurnal) variation). A typical model will have several diurnal time slices, and several seasonal time slices.

Utilisation: The percentage of an Asset's capacity that is actually used to produce its commodities. Must be between 0 and 1, and can be measured at time slice, season, or year level.

Variable Operating Cost: The variable operating cost charged per unit of activity of the Process.

Developer Guide

This is a guide for those who wish to contribute to the MUSE 2.0 project or make local changes to the code.

The API documentation is available here.

Background: The Rust programming language

MUSE 2.0 is written using Rust, which is a high-performance, compiled language. If you have used other compiled languages, such as C++, many of the concepts will be familiar. One feature which distinguishes it from other languages like C and C++, however, is that undefined behaviour, such as memory safety bugs, are not possible, provided you keep to the safe subset of the language. This means you can have the performance benefits of using a low-level language like C, with the safety guarantees and much of the convenience of a higher-level language like Python.

There is much high quality documentation available for learning Rust, but it is probably best to start with The Rust Programming Language book, which is freely available online.

Installing developer tools

To develop MUSE 2.0 locally you will need the following components:

  • Git
  • Rust development tools
  • C++ development tools (needed for bindings to the HiGHS solver)

You can either install the necessary developer tools locally on your machine manually (a bare metal installation) or use the provided development container. Bare metal installation should generally be preferred if you plan on doing substantial development, as you should get better performance locally (and therefore shorter compile times), as well as making it easier to interact with your local filesystem. Development containers provide a mechanism for installing all the tools you will need (into a Docker container) and are generally used either via Visual Studio Code running locally or GitHub Codespaces, which run on GitHub-provided virtual machines running remotely.

Option 1: Bare metal installation

Installing the Rust toolchain

We recommend that developers use rustup to install the Rust toolchain. Follow the instructions on the rustup website.

Once you have done so, select the stable toolchain (used by this project) as your default with:

rustup default stable

As the project uses the latest stable toolchain, you may see build errors if your toolchain is out of date. You can update to the latest version with:

rustup update stable

Installing C++ tools for HiGHS

The highs-sys crate requires a C++ compiler and CMake to be installed on your system. These may be installed already, but if you encounter errors during the build process for highs-sys (e.g. "Unable to find libclang"), you should follow the instructions in the highs-sys repository.

Option 2: Developing inside a container

If you wish to use the development container locally with Visual Studio Code, you should first install the Dev Containers extension. Note you will also need Docker to be installed locally. For more information, see the documentation.

You can use GitHub Codespaces to develop directly from your web browser. For more information, please see GitHub's guide. When you first create your Codespace, you will be asked whether you wish to install the recommended extensions and you should choose "yes".

Downloading the MUSE 2.0 source code

Unless you are developing in a GitHub Codespace (see above), you will need to download the MUSE 2.0 source code to your local machine before you can develop it. Like many projects, MUSE 2.0 is stored in a Git repository hosted on GitHub. Many IDEs, such as Visual Studio Code, provide an interface to clone Git repositories, but you can also use the Git command-line tool (see installation instructions), like so:

git clone https://github.com/EnergySystemsModellingLab/MUSE_2.0

The source code will now be available in a folder named MUSE_2.0.

Working with the project

To build the project, run:

cargo build

Note that if you just want to build-test the project (i.e. check for errors and warnings) without building an executable, you can use the cargo check command, which is much faster.

To run MUSE 2.0 with the "simple" example, you can run:

cargo run run examples/simple

(Note the two runs. The first is for cargo and the second is passed as an argument to the built muse2 program.)

Tests can be run with:

cargo test

More information is available in the official cargo book.

Checking test coverage

We use Codecov to check whether pull requests introduce code without tests.

To check coverage locally (i.e. to make sure newly written code has tests), we recommend using cargo-llvm-cov.

It can be installed with:

cargo install cargo-llvm-cov

Once installed, you can use it like so:

cargo llvm-cov --open

This will generate a report in HTML format showing which lines are not currently covered by tests and open it in your default browser.

Developing the documentation

We use mdBook for generating technical documentation.

If you are developing the documentation locally, you may want to check that your changes render correctly (especially if you are working with equations).

To do this, you first need to install mdBook:

cargo install mdbook

You can then view the documentation in your browser like so:

mdbook serve -o

Documenting file formats

Documentation for file formats of different input and output files used by MUSE 2.0 is automatically generated from schemas, stored in the schemas/ folder.

Files are either in TOML or CSV format. For TOML files, we use JSON schemas and for CSV files we use table schemas (a similar format).

The documentation is generated with the docs/file_formats/generate_docs.py script. To generate all docs, run:

python docs/file_formats/generate_docs.py

To generate just one kind of docs (e.g. for input files only), run:

python docs/file_formats/generate_docs.py input

Recreate the command_line_help.md file

This file is created automatically. In order to examine the output locally, run:

cargo run -- --markdown_help > docs/command_line_help.md

Pre-Commit hooks

Developers must install the pre-commit tool in order to automatically run this repository's hooks when making a new Git commit. Follow the instructions on the pre-commit website in order to get started.

Once you have installed pre-commit, you need to enable its use for this repository by installing the hooks, like so:

pre-commit install

Thereafter, a series of checks should be run every time you commit with Git. In addition, the pre-commit hooks are also run as part of the CI pipeline.

Note: you may get errors due to the clippy hook failing. In this case, you may be able to automatically fix them by running cargo clipfix (which we have defined as an alias in .cargo/config.toml).