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
34 changes: 34 additions & 0 deletions schemas/input/commodity_constraints.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
$schema: https://specs.frictionlessdata.io/schemas/table-schema.json
description: |
Specifies the limits on the total amount of consumption/production of a given
commodity in a given region, year and time slice(s).

fields:
- name: commodity_id
type: string
description: The commodity to which this constraint applies
- name: region_id
type: string
description: The region in which this constraint applies
- name: balance_type
type: string
description: The type of balance to which this is applied
notes:
Valid options are "cons" and "prod"; the "net" option is not valid here, as net
production is already constrained by the commodity balance constraints.
- name: years
type: string
description: The year(s) to which this entry applies
- name: time_slice
type: string
description: The time slice(s) to which this entry applies
Comment thread
dc2917 marked this conversation as resolved.
notes: |
Can be a single time slice (e.g. `winter.day`), a whole season (e.g. `winter`) or `annual`,
representing the whole year
- name: limits
type: string
description: Lower and upper limits on the value of the commodity
notes:
A string in the format `min..max`, where `min` and `max` are decimal numbers
(e.g. "0.12..78.9"). Either `min` or `max` can be omitted (e.g "0.12.." or
"..78.9"), which will set the corresponding limit to 0 or infinite, respectively.
22 changes: 22 additions & 0 deletions src/commodity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::units::{Flow, MoneyPerFlow};
use indexmap::IndexMap;
use serde::Deserialize;
use std::collections::HashMap;
use std::ops::RangeInclusive;
use std::sync::Arc;

define_id_type! {CommodityID, "commodity ID"}
Expand All @@ -16,6 +17,9 @@ pub type CommodityMap = IndexMap<CommodityID, Arc<Commodity>>;
/// A map of [`MoneyPerFlow`]s, keyed by region ID, year and time slice ID for a specific levy
pub type CommodityLevyMap = HashMap<(RegionID, u32, TimeSliceID), MoneyPerFlow>;

/// A map of vectors of [`CommodityConstraint`]s, keyed by region ID and year
pub type CommodityConstraintsMap = HashMap<(RegionID, u32), Vec<CommodityConstraint>>;

/// A map of demand values, keyed by region ID, year and time slice selection
pub type DemandMap = HashMap<(RegionID, u32, TimeSliceSelection), Flow>;

Expand Down Expand Up @@ -53,6 +57,11 @@ pub struct Commodity {
/// `time_slice_level` field. E.g. if the `time_slice_level` is seasonal, then there will be
/// keys representing each season (and not e.g. individual time slices).
pub demand: DemandMap,
/// Constraints for this commodity for different combinations of region, year and time slice.
///
/// May be empty if there are no constraints for this commodity, otherwise there must be entries
/// for every combination of parameters.
pub constraints: CommodityConstraintsMap,
/// Units for this commodity represented as a string e.g Petajoules, Tonnes
/// This is only used for validation purposes.
pub units: String,
Expand Down Expand Up @@ -115,6 +124,19 @@ pub enum PricingStrategy {
Unpriced,
}

/// A constraint imposed on commodity values
#[derive(PartialEq, Debug, Clone)]
pub struct CommodityConstraint {
/// The balance type for the commodity constraint
pub balance_type: BalanceType,
/// The time slice selection for the commodity constraint
pub ts_selection: TimeSliceSelection,
/// The range of values the commodity is constrained to lie between
pub limits: RangeInclusive<Flow>,
}

impl CommodityConstraint {}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
6 changes: 5 additions & 1 deletion src/fixture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use crate::agent::{
};
use crate::asset::{Asset, AssetCapacity, AssetPool, AssetRef};
use crate::commodity::{
Commodity, CommodityID, CommodityLevyMap, CommodityType, DemandMap, PricingStrategy,
Commodity, CommodityConstraintsMap, CommodityID, CommodityLevyMap, CommodityType, DemandMap,
PricingStrategy,
};
use crate::patch::{FilePatch, ModelPatch};
use crate::process::{
Expand Down Expand Up @@ -157,6 +158,7 @@ pub fn svd_commodity() -> Commodity {
levies_prod: CommodityLevyMap::new(),
levies_cons: CommodityLevyMap::new(),
demand: DemandMap::new(),
constraints: CommodityConstraintsMap::new(),
units: "PJ".into(),
}
}
Expand All @@ -172,6 +174,7 @@ pub fn sed_commodity() -> Commodity {
levies_prod: CommodityLevyMap::new(),
levies_cons: CommodityLevyMap::new(),
demand: DemandMap::new(),
constraints: CommodityConstraintsMap::new(),
units: "PJ".into(),
}
}
Expand All @@ -187,6 +190,7 @@ pub fn other_commodity() -> Commodity {
levies_prod: CommodityLevyMap::new(),
levies_cons: CommodityLevyMap::new(),
demand: DemandMap::new(),
constraints: CommodityConstraintsMap::new(),
units: "PJ".into(),
}
}
Expand Down
20 changes: 18 additions & 2 deletions src/input/commodity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
use super::{input_err_msg, read_csv};
use crate::ISSUES_URL;
use crate::commodity::{
BalanceType, Commodity, CommodityID, CommodityLevyMap, CommodityMap, CommodityType, DemandMap,
PricingStrategy,
BalanceType, Commodity, CommodityConstraintsMap, CommodityID, CommodityLevyMap, CommodityMap,
CommodityType, DemandMap, PricingStrategy,
};
use crate::model::{ALLOW_DANGEROUS_OPTION_NAME, dangerous_model_options_enabled};
use crate::region::RegionID;
Expand All @@ -16,6 +16,8 @@ use std::path::Path;

mod levy;
use levy::read_commodity_levies;
mod constraints;
use constraints::read_commodity_constraints;
mod demand;
use demand::read_demand;
mod demand_slicing;
Expand Down Expand Up @@ -55,6 +57,15 @@ pub fn read_commodities(
let commodities = read_commodities_file(model_dir)?;
let commodity_ids = commodities.keys().cloned().collect();

// Read constraints table
let mut commodity_constraints = read_commodity_constraints(
model_dir,
&commodities,
region_ids,
time_slice_info,
milestone_years,
)?;

// Read costs table
let mut costs = read_commodity_levies(
model_dir,
Expand Down Expand Up @@ -88,6 +99,9 @@ pub fn read_commodities(
if let Some(demand) = demand.remove(&id) {
commodity.demand = demand;
}
if let Some(commodity_constraints) = commodity_constraints.remove(&id) {
commodity.constraints = commodity_constraints;
}

(id, commodity.into())
})
Expand Down Expand Up @@ -120,6 +134,7 @@ where
levies_prod: CommodityLevyMap::default(),
levies_cons: CommodityLevyMap::default(),
demand: DemandMap::default(),
constraints: CommodityConstraintsMap::default(),
units: commodity_raw.units,
};

Expand Down Expand Up @@ -206,6 +221,7 @@ mod tests {
levies_prod: CommodityLevyMap::default(),
levies_cons: CommodityLevyMap::default(),
demand: DemandMap::default(),
constraints: CommodityConstraintsMap::default(),
units: "PJ".into(),
}
}
Expand Down
Loading
Loading