Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 7 additions & 19 deletions docs/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

**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. The
*Primary Activity Commodity* specifies which output/s or input/s are linked to the *Process*
capacity.
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
Expand All @@ -27,14 +25,9 @@ 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*, as measured by units of the *Primary
Activity Commodity*.
**Capacity:** The maximum output (or input) of an *Asset*.

**Capital Cost:** The overnight capital cost of a process, measured in units of the *Primary
Activity Commodity* divided by CAP2ACT. CAP2ACT is a factor that converts 1 unit of capacity to
maximum activity of the primary activity commodity/ies per year. For example, if capacity is
measured in GW and activity is measured in PJ, CAP2ACT for the process is 31.536 because 1 GW of
capacity can produce 31.536 PJ energy output in a year.
**Capital Cost:** The overnight capital cost of a process.

<!-- markdownlint-disable-next-line MD033 -->
**Commodity:** A substance (e.g. CO<sub>2</sub>) or form of energy (e.g. electricity) that can be
Expand Down Expand Up @@ -79,10 +72,6 @@ the next most expensive, etc, until demand is served. Also called “unit commit

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

**Primary Activity Commodity (PAC):** The PACs specify which output/s are linked to the *Process*
capacity. The combined output of all PACs cannot exceed the *Asset's* capacity. A user can define
which output/s are PACs. Most, but not all *Process*es will have only one PAC.

**Process:** A blueprint of an available *Process* that converts input commodities to output
commodities. *Process*es 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
Expand Down Expand Up @@ -114,9 +103,8 @@ Levelised Cost of X, etc.
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 *Primary
Activity Commodities*. Must be between 0 and 1, and can be measured at time slice, season, or year
level.
**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 input or output of the
*Primary Activity Commodity* of the *Process*.
**Variable Operating Cost:** The variable operating cost charged per unit of activity of the
*Process*.
30 changes: 15 additions & 15 deletions examples/simple/process_flows.csv
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
process_id,commodity_id,regions,years,coeff,type,cost,is_pac
GASDRV,GASPRD,all,all,1.0,fixed,,true
GASPRC,GASPRD,all,all,-1.05,fixed,,false
GASPRC,GASNAT,all,all,1.0,fixed,,true
WNDFRM,ELCTRI,all,all,1.0,fixed,,true
GASCGT,GASNAT,all,all,-1.5,fixed,,false
GASCGT,ELCTRI,all,all,1.0,fixed,,true
RGASBR,GASNAT,all,all,-1.15,fixed,,false
RGASBR,RSHEAT,all,all,1.0,fixed,,true
RELCHP,ELCTRI,all,all,-0.33,fixed,,true
RELCHP,RSHEAT,all,all,1.0,fixed,,false
GASDRV,CO2EMT,all,all,5.113,fixed,,false
GASPRC,CO2EMT,all,all,2.5565,fixed,,false
GASCGT,CO2EMT,all,all,76.695,fixed,,false
RGASBR,CO2EMT,all,all,58.7995,fixed,,false
process_id,commodity_id,regions,years,coeff,type,cost
GASDRV,GASPRD,all,all,1.0,fixed,
GASPRC,GASPRD,all,all,-1.05,fixed,
GASPRC,GASNAT,all,all,1.0,fixed,
WNDFRM,ELCTRI,all,all,1.0,fixed,
GASCGT,GASNAT,all,all,-1.5,fixed,
GASCGT,ELCTRI,all,all,1.0,fixed,
RGASBR,GASNAT,all,all,-1.15,fixed,
RGASBR,RSHEAT,all,all,1.0,fixed,
RELCHP,ELCTRI,all,all,-0.33,fixed,
RELCHP,RSHEAT,all,all,1.0,fixed,
GASDRV,CO2EMT,all,all,5.113,fixed,
GASPRC,CO2EMT,all,all,2.5565,fixed,
GASCGT,CO2EMT,all,all,76.695,fixed,
RGASBR,CO2EMT,all,all,58.7995,fixed,
8 changes: 0 additions & 8 deletions schemas/input/process_flows.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ 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.
- One (and only one) commodity flow for each region/year must be designated as the primary
activity commodity (PAC).

fields:
- name: process_id
Expand Down Expand Up @@ -38,9 +36,3 @@ fields:
type: number
description: The cost per unit flow
notes: Optional. If present, must be >0.
- name: is_pac
type: boolean
description: Whether this commodity flow is a primary activity commodity (PAC)
notes: |
One and only one commodity flow can be a PAC for a given combination of region and milestone
year
4 changes: 2 additions & 2 deletions schemas/input/process_parameters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ fields:
description: Annual operating cost per unit capacity
- name: variable_operating_cost
type: number
description: Annual variable operating cost per unit activity, for PACs **only**
description: Annual variable operating cost per unit activity
- name: lifetime
type: integer
description: Lifetime in years of an asset created from this process
Expand All @@ -38,5 +38,5 @@ fields:
notes: Must be positive. A warning will be issued if this number is >1.
- name: capacity_to_activity
type: number
description: Factor for calculating the maximum PAC consumption/production over a year.
description: Factor for calculating the maximum consumption/production over a year.
notes: Must be >=0
31 changes: 11 additions & 20 deletions src/asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,11 @@ impl Asset {
self.commission_year + self.process_parameter.lifetime
}

/// Get the energy limits for this asset in a particular time slice
///
/// This is an absolute max and min on the PAC energy produced/consumed in that time slice.
pub fn get_energy_limits(&self, time_slice: &TimeSliceID) -> RangeInclusive<f64> {
/// Get the activity limits for this asset in a particular time slice
pub fn get_activity_limits(&self, time_slice: &TimeSliceID) -> RangeInclusive<f64> {
let limits = self
.process
.energy_limits
.activity_limits
.get(&(
self.region_id.clone(),
self.commission_year,
Expand All @@ -100,12 +98,11 @@ impl Asset {
.unwrap();
let max_act = self.maximum_activity();

// Multiply the fractional energy limits by this asset's maximum activity to get energy
// limits in real units (which are user defined)
(max_act * limits.start())..=(max_act * limits.end())
}

/// Maximum activity for this asset (PAC energy produced/consumed per year)
/// Maximum activity for this asset
pub fn maximum_activity(&self) -> f64 {
self.capacity * self.process_parameter.capacity_to_activity
}
Expand All @@ -127,12 +124,6 @@ impl Asset {
pub fn iter_flows(&self) -> impl Iterator<Item = &ProcessFlow> {
self.get_flows_map().values()
}

/// Iterate over the asset's Primary Activity Commodity flows
pub fn iter_pacs(&self) -> impl Iterator<Item = &ProcessFlow> {
self.process
.iter_pacs(&self.region_id, self.commission_year)
}
}

/// A wrapper around [`Asset`] for storing references in maps.
Expand Down Expand Up @@ -318,7 +309,7 @@ mod tests {
use super::*;
use crate::fixture::{assert_error, process};
use crate::process::{
Process, ProcessEnergyLimitsMap, ProcessFlowsMap, ProcessParameter, ProcessParameterMap,
Process, ProcessActivityLimitsMap, ProcessFlowsMap, ProcessParameter, ProcessParameterMap,
};
use itertools::{assert_equal, Itertools};
use rstest::{fixture, rstest};
Expand Down Expand Up @@ -393,7 +384,7 @@ mod tests {
id: "process1".into(),
description: "Description".into(),
years: vec![2010, 2020],
energy_limits: ProcessEnergyLimitsMap::new(),
activity_limits: ProcessActivityLimitsMap::new(),
flows: ProcessFlowsMap::new(),
parameters: process_parameter_map,
regions: HashSet::from(["GBR".into()]),
Expand All @@ -416,7 +407,7 @@ mod tests {
}

#[test]
fn test_asset_get_energy_limits() {
fn test_asset_get_activity_limits() {
let time_slice = TimeSliceID {
season: "winter".into(),
time_of_day: "day".into(),
Expand All @@ -435,9 +426,9 @@ mod tests {
.map(|&year| (("GBR".into(), year), process_param.clone()))
.collect();
let fraction_limits = 1.0..=f64::INFINITY;
let mut energy_limits = ProcessEnergyLimitsMap::new();
let mut activity_limits = ProcessActivityLimitsMap::new();
for year in [2010, 2020] {
energy_limits.insert(
activity_limits.insert(
("GBR".into(), year, time_slice.clone()),
fraction_limits.clone(),
);
Expand All @@ -446,7 +437,7 @@ mod tests {
id: "process1".into(),
description: "Description".into(),
years: vec![2010, 2020],
energy_limits,
activity_limits,
flows: ProcessFlowsMap::new(),
parameters: process_parameter_map,
regions: HashSet::from(["GBR".into()]),
Expand All @@ -460,7 +451,7 @@ mod tests {
)
.unwrap();

assert_eq!(asset.get_energy_limits(&time_slice), 6.0..=f64::INFINITY);
assert_eq!(asset.get_activity_limits(&time_slice), 6.0..=f64::INFINITY);
}

#[rstest]
Expand Down
4 changes: 2 additions & 2 deletions src/fixture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::agent::{
use crate::asset::{Asset, AssetPool};
use crate::commodity::{Commodity, CommodityID, CommodityLevyMap, CommodityType, DemandMap};
use crate::process::{
Process, ProcessEnergyLimitsMap, ProcessFlowsMap, ProcessMap, ProcessParameter,
Process, ProcessActivityLimitsMap, ProcessFlowsMap, ProcessMap, ProcessParameter,
ProcessParameterMap,
};
use crate::region::RegionID;
Expand Down Expand Up @@ -114,7 +114,7 @@ pub fn process(
id: "process1".into(),
description: "Description".into(),
years: vec![2010, 2020],
energy_limits: ProcessEnergyLimitsMap::new(),
activity_limits: ProcessActivityLimitsMap::new(),
flows: ProcessFlowsMap::new(),
parameters: process_parameter_map,
regions: region_ids,
Expand Down
6 changes: 4 additions & 2 deletions src/input/agent/search_space.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,9 @@ where
mod tests {
use super::*;
use crate::fixture::{agents, assert_error, region_ids};
use crate::process::{ProcessEnergyLimitsMap, ProcessFlowsMap, ProcessID, ProcessParameterMap};
use crate::process::{
ProcessActivityLimitsMap, ProcessFlowsMap, ProcessID, ProcessParameterMap,
};
use crate::region::RegionID;
use rstest::{fixture, rstest};
use std::iter;
Expand All @@ -171,7 +173,7 @@ mod tests {
id: id.clone(),
description: "Description".into(),
years: vec![2010, 2020],
energy_limits: ProcessEnergyLimitsMap::new(),
activity_limits: ProcessActivityLimitsMap::new(),
flows: ProcessFlowsMap::new(),
parameters: ProcessParameterMap::new(),
regions: region_ids.clone(),
Expand Down
21 changes: 9 additions & 12 deletions src/input/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use super::*;
use crate::commodity::{Commodity, CommodityID, CommodityMap, CommodityType};
use crate::process::{
Process, ProcessEnergyLimitsMap, ProcessFlowsMap, ProcessID, ProcessMap, ProcessParameterMap,
Process, ProcessActivityLimitsMap, ProcessFlowsMap, ProcessID, ProcessMap, ProcessParameterMap,
};
use crate::region::{parse_region_str, RegionID};
use crate::time_slice::{TimeSliceInfo, TimeSliceSelection};
Expand Down Expand Up @@ -55,7 +55,7 @@ pub fn read_processes(
let mut processes = read_processes_file(model_dir, milestone_years, region_ids)?;
let process_ids = processes.keys().cloned().collect();

let mut energy_limits =
let mut activity_limits =
read_process_availabilities(model_dir, &process_ids, &processes, time_slice_info)?;
let mut flows = read_process_flows(model_dir, &process_ids, &processes, commodities)?;
let mut parameters = read_process_parameters(model_dir, &process_ids, &processes)?;
Expand All @@ -64,15 +64,15 @@ pub fn read_processes(
validate_commodities(
commodities,
&flows,
&energy_limits,
&activity_limits,
region_ids,
milestone_years,
time_slice_info,
)?;

// Add data to Process objects
for (id, process) in processes.iter_mut() {
process.energy_limits = energy_limits
process.activity_limits = activity_limits
.remove(id)
.with_context(|| format!("Missing availabilities for process {id}"))?;
process.flows = flows
Expand Down Expand Up @@ -139,7 +139,7 @@ where
id: process_raw.id.clone(),
description: process_raw.description,
years,
energy_limits: ProcessEnergyLimitsMap::new(),
activity_limits: ProcessActivityLimitsMap::new(),
flows: ProcessFlowsMap::new(),
parameters: ProcessParameterMap::new(),
regions,
Expand All @@ -158,7 +158,7 @@ where
fn validate_commodities(
commodities: &CommodityMap,
flows: &HashMap<ProcessID, ProcessFlowsMap>,
availabilities: &HashMap<ProcessID, ProcessEnergyLimitsMap>,
availabilities: &HashMap<ProcessID, ProcessActivityLimitsMap>,
region_ids: &HashSet<RegionID>,
milestone_years: &[u32],
time_slice_info: &TimeSliceInfo,
Expand Down Expand Up @@ -227,7 +227,7 @@ fn validate_svd_commodity(
time_slice_info: &TimeSliceInfo,
commodity: &Commodity,
flows: &HashMap<ProcessID, ProcessFlowsMap>,
availabilities: &HashMap<ProcessID, ProcessEnergyLimitsMap>,
availabilities: &HashMap<ProcessID, ProcessActivityLimitsMap>,
region_id: &RegionID,
year: &u32,
ts_selection: &TimeSliceSelection,
Expand Down Expand Up @@ -308,7 +308,6 @@ mod tests {
coeff: -10.0,
kind: FlowType::Fixed,
cost: 1.0,
is_pac: false,
}},
)])
}
Expand All @@ -322,7 +321,6 @@ mod tests {
coeff: 10.0,
kind: FlowType::Fixed,
cost: 1.0,
is_pac: false,
}},
)])
}
Expand Down Expand Up @@ -383,7 +381,6 @@ mod tests {
coeff: 10.0,
kind: FlowType::Fixed,
cost: 1.0,
is_pac: false,
}},
)]),
)])
Expand All @@ -398,7 +395,7 @@ mod tests {
) {
let availabilities = HashMap::from_iter(vec![(
"process1".into(),
ProcessEnergyLimitsMap::from_iter(vec![(
ProcessActivityLimitsMap::from_iter(vec![(
("GBR".into(), 2010, time_slice.clone()),
0.1..=0.9,
)]),
Expand Down Expand Up @@ -427,7 +424,7 @@ mod tests {
// Invalid scenario: no availability
let availabilities = HashMap::from_iter(vec![(
"process1".into(),
ProcessEnergyLimitsMap::from_iter(vec![(
ProcessActivityLimitsMap::from_iter(vec![(
("GBR".into(), 2010, time_slice.clone()),
0.0..=0.0,
)]),
Expand Down
Loading