Skip to content

Commit 5ff7770

Browse files
authored
Merge pull request #614 from EnergySystemsModellingLab/remove-pacs
Remove PACs from code and documentation
2 parents 0b52f84 + 552d469 commit 5ff7770

12 files changed

Lines changed: 93 additions & 249 deletions

File tree

docs/glossary.md

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22

33
**Activity:** The flow of input/s or output/s of a *Process* that are limited by its capacity. For
44
example, a 500MW power station can output 500MWh per hour of electrical power, or a 50MW
5-
electrolyser consumes up to 50MWh per hour of electrical power to produce hydrogen. The
6-
*Primary Activity Commodity* specifies which output/s or input/s are linked to the *Process*
7-
capacity.
5+
electrolyser consumes up to 50MWh per hour of electrical power to produce hydrogen.
86

97
**Agent:** A decision-making entity in the system. An *Agent* is responsible for serving a
108
user-specified portion of a *Commodity* demand or *Service Demand*. *Agents* invest in and operate
@@ -27,14 +25,9 @@ data, including **Process** stock and commodity consumption/production.
2725
**Calibration:** The act of ensuring that the model represents the system being modelled in a
2826
historical base year.
2927

30-
**Capacity:** The maximum output (or input) of an *Asset*, as measured by units of the *Primary
31-
Activity Commodity*.
28+
**Capacity:** The maximum output (or input) of an *Asset*.
3229

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

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

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

82-
**Primary Activity Commodity (PAC):** The PACs specify which output/s are linked to the *Process*
83-
capacity. The combined output of all PACs cannot exceed the *Asset's* capacity. A user can define
84-
which output/s are PACs. Most, but not all *Process*es will have only one PAC.
85-
8675
**Process:** A blueprint of an available *Process* that converts input commodities to output
8776
commodities. *Process*es have economic attributes of capital cost, fixed operating cost per unit
8877
capacity, non-fuel variable operating cost per unit activity, and risk discount rate. They have
@@ -114,9 +103,8 @@ Levelised Cost of X, etc.
114103
a model does not represent seasons or within-day (diurnal) variation). A typical model will have
115104
several diurnal time slices, and several seasonal time slices.
116105

117-
**Utilisation:** The percentage of an *Asset*s capacity that is actually used to produce *Primary
118-
Activity Commodities*. Must be between 0 and 1, and can be measured at time slice, season, or year
119-
level.
106+
**Utilisation:** The percentage of an *Asset*'s capacity that is actually used to produce its
107+
commodities. Must be between 0 and 1, and can be measured at time slice, season, or year level.
120108

121-
**Variable Operating Cost:** The variable operating cost charged per unit of input or output of the
122-
*Primary Activity Commodity* of the *Process*.
109+
**Variable Operating Cost:** The variable operating cost charged per unit of activity of the
110+
*Process*.

examples/simple/process_flows.csv

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
process_id,commodity_id,regions,years,coeff,type,cost,is_pac
2-
GASDRV,GASPRD,all,all,1.0,fixed,,true
3-
GASPRC,GASPRD,all,all,-1.05,fixed,,false
4-
GASPRC,GASNAT,all,all,1.0,fixed,,true
5-
WNDFRM,ELCTRI,all,all,1.0,fixed,,true
6-
GASCGT,GASNAT,all,all,-1.5,fixed,,false
7-
GASCGT,ELCTRI,all,all,1.0,fixed,,true
8-
RGASBR,GASNAT,all,all,-1.15,fixed,,false
9-
RGASBR,RSHEAT,all,all,1.0,fixed,,true
10-
RELCHP,ELCTRI,all,all,-0.33,fixed,,true
11-
RELCHP,RSHEAT,all,all,1.0,fixed,,false
12-
GASDRV,CO2EMT,all,all,5.113,fixed,,false
13-
GASPRC,CO2EMT,all,all,2.5565,fixed,,false
14-
GASCGT,CO2EMT,all,all,76.695,fixed,,false
15-
RGASBR,CO2EMT,all,all,58.7995,fixed,,false
1+
process_id,commodity_id,regions,years,coeff,type,cost
2+
GASDRV,GASPRD,all,all,1.0,fixed,
3+
GASPRC,GASPRD,all,all,-1.05,fixed,
4+
GASPRC,GASNAT,all,all,1.0,fixed,
5+
WNDFRM,ELCTRI,all,all,1.0,fixed,
6+
GASCGT,GASNAT,all,all,-1.5,fixed,
7+
GASCGT,ELCTRI,all,all,1.0,fixed,
8+
RGASBR,GASNAT,all,all,-1.15,fixed,
9+
RGASBR,RSHEAT,all,all,1.0,fixed,
10+
RELCHP,ELCTRI,all,all,-0.33,fixed,
11+
RELCHP,RSHEAT,all,all,1.0,fixed,
12+
GASDRV,CO2EMT,all,all,5.113,fixed,
13+
GASPRC,CO2EMT,all,all,2.5565,fixed,
14+
GASCGT,CO2EMT,all,all,76.695,fixed,
15+
RGASBR,CO2EMT,all,all,58.7995,fixed,

schemas/input/process_flows.yaml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ notes:
55
- Commodity flows can vary by region and year.
66
- For each process, there must be entries covering all the years and regions in which the process
77
operates.
8-
- One (and only one) commodity flow for each region/year must be designated as the primary
9-
activity commodity (PAC).
108

119
fields:
1210
- name: process_id
@@ -38,9 +36,3 @@ fields:
3836
type: number
3937
description: The cost per unit flow
4038
notes: Optional. If present, must be >0.
41-
- name: is_pac
42-
type: boolean
43-
description: Whether this commodity flow is a primary activity commodity (PAC)
44-
notes: |
45-
One and only one commodity flow can be a PAC for a given combination of region and milestone
46-
year

schemas/input/process_parameters.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ fields:
2727
description: Annual operating cost per unit capacity
2828
- name: variable_operating_cost
2929
type: number
30-
description: Annual variable operating cost per unit activity, for PACs **only**
30+
description: Annual variable operating cost per unit activity
3131
- name: lifetime
3232
type: integer
3333
description: Lifetime in years of an asset created from this process
@@ -38,5 +38,5 @@ fields:
3838
notes: Must be positive. A warning will be issued if this number is >1.
3939
- name: capacity_to_activity
4040
type: number
41-
description: Factor for calculating the maximum PAC consumption/production over a year.
41+
description: Factor for calculating the maximum consumption/production over a year.
4242
notes: Must be >=0

src/asset.rs

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,11 @@ impl Asset {
8585
self.commission_year + self.process_parameter.lifetime
8686
}
8787

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

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

108-
/// Maximum activity for this asset (PAC energy produced/consumed per year)
105+
/// Maximum activity for this asset
109106
pub fn maximum_activity(&self) -> f64 {
110107
self.capacity * self.process_parameter.capacity_to_activity
111108
}
@@ -127,12 +124,6 @@ impl Asset {
127124
pub fn iter_flows(&self) -> impl Iterator<Item = &ProcessFlow> {
128125
self.get_flows_map().values()
129126
}
130-
131-
/// Iterate over the asset's Primary Activity Commodity flows
132-
pub fn iter_pacs(&self) -> impl Iterator<Item = &ProcessFlow> {
133-
self.process
134-
.iter_pacs(&self.region_id, self.commission_year)
135-
}
136127
}
137128

138129
/// A wrapper around [`Asset`] for storing references in maps.
@@ -318,7 +309,7 @@ mod tests {
318309
use super::*;
319310
use crate::fixture::{assert_error, process};
320311
use crate::process::{
321-
Process, ProcessEnergyLimitsMap, ProcessFlowsMap, ProcessParameter, ProcessParameterMap,
312+
Process, ProcessActivityLimitsMap, ProcessFlowsMap, ProcessParameter, ProcessParameterMap,
322313
};
323314
use itertools::{assert_equal, Itertools};
324315
use rstest::{fixture, rstest};
@@ -393,7 +384,7 @@ mod tests {
393384
id: "process1".into(),
394385
description: "Description".into(),
395386
years: vec![2010, 2020],
396-
energy_limits: ProcessEnergyLimitsMap::new(),
387+
activity_limits: ProcessActivityLimitsMap::new(),
397388
flows: ProcessFlowsMap::new(),
398389
parameters: process_parameter_map,
399390
regions: HashSet::from(["GBR".into()]),
@@ -416,7 +407,7 @@ mod tests {
416407
}
417408

418409
#[test]
419-
fn test_asset_get_energy_limits() {
410+
fn test_asset_get_activity_limits() {
420411
let time_slice = TimeSliceID {
421412
season: "winter".into(),
422413
time_of_day: "day".into(),
@@ -435,9 +426,9 @@ mod tests {
435426
.map(|&year| (("GBR".into(), year), process_param.clone()))
436427
.collect();
437428
let fraction_limits = 1.0..=f64::INFINITY;
438-
let mut energy_limits = ProcessEnergyLimitsMap::new();
429+
let mut activity_limits = ProcessActivityLimitsMap::new();
439430
for year in [2010, 2020] {
440-
energy_limits.insert(
431+
activity_limits.insert(
441432
("GBR".into(), year, time_slice.clone()),
442433
fraction_limits.clone(),
443434
);
@@ -446,7 +437,7 @@ mod tests {
446437
id: "process1".into(),
447438
description: "Description".into(),
448439
years: vec![2010, 2020],
449-
energy_limits,
440+
activity_limits,
450441
flows: ProcessFlowsMap::new(),
451442
parameters: process_parameter_map,
452443
regions: HashSet::from(["GBR".into()]),
@@ -460,7 +451,7 @@ mod tests {
460451
)
461452
.unwrap();
462453

463-
assert_eq!(asset.get_energy_limits(&time_slice), 6.0..=f64::INFINITY);
454+
assert_eq!(asset.get_activity_limits(&time_slice), 6.0..=f64::INFINITY);
464455
}
465456

466457
#[rstest]

src/fixture.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::agent::{
77
use crate::asset::{Asset, AssetPool};
88
use crate::commodity::{Commodity, CommodityID, CommodityLevyMap, CommodityType, DemandMap};
99
use crate::process::{
10-
Process, ProcessEnergyLimitsMap, ProcessFlowsMap, ProcessMap, ProcessParameter,
10+
Process, ProcessActivityLimitsMap, ProcessFlowsMap, ProcessMap, ProcessParameter,
1111
ProcessParameterMap,
1212
};
1313
use crate::region::RegionID;
@@ -114,7 +114,7 @@ pub fn process(
114114
id: "process1".into(),
115115
description: "Description".into(),
116116
years: vec![2010, 2020],
117-
energy_limits: ProcessEnergyLimitsMap::new(),
117+
activity_limits: ProcessActivityLimitsMap::new(),
118118
flows: ProcessFlowsMap::new(),
119119
parameters: process_parameter_map,
120120
regions: region_ids,

src/input/agent/search_space.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,9 @@ where
157157
mod tests {
158158
use super::*;
159159
use crate::fixture::{agents, assert_error, region_ids};
160-
use crate::process::{ProcessEnergyLimitsMap, ProcessFlowsMap, ProcessID, ProcessParameterMap};
160+
use crate::process::{
161+
ProcessActivityLimitsMap, ProcessFlowsMap, ProcessID, ProcessParameterMap,
162+
};
161163
use crate::region::RegionID;
162164
use rstest::{fixture, rstest};
163165
use std::iter;
@@ -171,7 +173,7 @@ mod tests {
171173
id: id.clone(),
172174
description: "Description".into(),
173175
years: vec![2010, 2020],
174-
energy_limits: ProcessEnergyLimitsMap::new(),
176+
activity_limits: ProcessActivityLimitsMap::new(),
175177
flows: ProcessFlowsMap::new(),
176178
parameters: ProcessParameterMap::new(),
177179
regions: region_ids.clone(),

src/input/process.rs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
use super::*;
33
use crate::commodity::{Commodity, CommodityID, CommodityMap, CommodityType};
44
use crate::process::{
5-
Process, ProcessEnergyLimitsMap, ProcessFlowsMap, ProcessID, ProcessMap, ProcessParameterMap,
5+
Process, ProcessActivityLimitsMap, ProcessFlowsMap, ProcessID, ProcessMap, ProcessParameterMap,
66
};
77
use crate::region::{parse_region_str, RegionID};
88
use crate::time_slice::{TimeSliceInfo, TimeSliceSelection};
@@ -55,7 +55,7 @@ pub fn read_processes(
5555
let mut processes = read_processes_file(model_dir, milestone_years, region_ids)?;
5656
let process_ids = processes.keys().cloned().collect();
5757

58-
let mut energy_limits =
58+
let mut activity_limits =
5959
read_process_availabilities(model_dir, &process_ids, &processes, time_slice_info)?;
6060
let mut flows = read_process_flows(model_dir, &process_ids, &processes, commodities)?;
6161
let mut parameters = read_process_parameters(model_dir, &process_ids, &processes)?;
@@ -64,15 +64,15 @@ pub fn read_processes(
6464
validate_commodities(
6565
commodities,
6666
&flows,
67-
&energy_limits,
67+
&activity_limits,
6868
region_ids,
6969
milestone_years,
7070
time_slice_info,
7171
)?;
7272

7373
// Add data to Process objects
7474
for (id, process) in processes.iter_mut() {
75-
process.energy_limits = energy_limits
75+
process.activity_limits = activity_limits
7676
.remove(id)
7777
.with_context(|| format!("Missing availabilities for process {id}"))?;
7878
process.flows = flows
@@ -139,7 +139,7 @@ where
139139
id: process_raw.id.clone(),
140140
description: process_raw.description,
141141
years,
142-
energy_limits: ProcessEnergyLimitsMap::new(),
142+
activity_limits: ProcessActivityLimitsMap::new(),
143143
flows: ProcessFlowsMap::new(),
144144
parameters: ProcessParameterMap::new(),
145145
regions,
@@ -158,7 +158,7 @@ where
158158
fn validate_commodities(
159159
commodities: &CommodityMap,
160160
flows: &HashMap<ProcessID, ProcessFlowsMap>,
161-
availabilities: &HashMap<ProcessID, ProcessEnergyLimitsMap>,
161+
availabilities: &HashMap<ProcessID, ProcessActivityLimitsMap>,
162162
region_ids: &HashSet<RegionID>,
163163
milestone_years: &[u32],
164164
time_slice_info: &TimeSliceInfo,
@@ -227,7 +227,7 @@ fn validate_svd_commodity(
227227
time_slice_info: &TimeSliceInfo,
228228
commodity: &Commodity,
229229
flows: &HashMap<ProcessID, ProcessFlowsMap>,
230-
availabilities: &HashMap<ProcessID, ProcessEnergyLimitsMap>,
230+
availabilities: &HashMap<ProcessID, ProcessActivityLimitsMap>,
231231
region_id: &RegionID,
232232
year: &u32,
233233
ts_selection: &TimeSliceSelection,
@@ -308,7 +308,6 @@ mod tests {
308308
coeff: -10.0,
309309
kind: FlowType::Fixed,
310310
cost: 1.0,
311-
is_pac: false,
312311
}},
313312
)])
314313
}
@@ -322,7 +321,6 @@ mod tests {
322321
coeff: 10.0,
323322
kind: FlowType::Fixed,
324323
cost: 1.0,
325-
is_pac: false,
326324
}},
327325
)])
328326
}
@@ -383,7 +381,6 @@ mod tests {
383381
coeff: 10.0,
384382
kind: FlowType::Fixed,
385383
cost: 1.0,
386-
is_pac: false,
387384
}},
388385
)]),
389386
)])
@@ -398,7 +395,7 @@ mod tests {
398395
) {
399396
let availabilities = HashMap::from_iter(vec![(
400397
"process1".into(),
401-
ProcessEnergyLimitsMap::from_iter(vec![(
398+
ProcessActivityLimitsMap::from_iter(vec![(
402399
("GBR".into(), 2010, time_slice.clone()),
403400
0.1..=0.9,
404401
)]),
@@ -427,7 +424,7 @@ mod tests {
427424
// Invalid scenario: no availability
428425
let availabilities = HashMap::from_iter(vec![(
429426
"process1".into(),
430-
ProcessEnergyLimitsMap::from_iter(vec![(
427+
ProcessActivityLimitsMap::from_iter(vec![(
431428
("GBR".into(), 2010, time_slice.clone()),
432429
0.0..=0.0,
433430
)]),

0 commit comments

Comments
 (0)