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
5 changes: 5 additions & 0 deletions examples/simple/agent_cost_limits.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
agent_id,year,capex_limit,annual_cost_limit
A0_GEX,all,,
A0_GPR,all,,
A0_ELC,all,,
A0_RES,all,,
10 changes: 5 additions & 5 deletions examples/simple/agents.csv
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
id,description,decision_rule,capex_limit,annual_cost_limit,decision_lexico_tolerance
A0_GEX,Gas extractors,single,,,
A0_GPR,Gas processors,single,,,
A0_ELC,Electricity generators,single,,,
A0_RES,Residential consumer,single,,,
id,description,decision_rule,decision_lexico_tolerance
A0_GEX,Gas extractors,single,
A0_GPR,Gas processors,single,
A0_ELC,Electricity generators,single,
A0_RES,Residential consumer,single,
19 changes: 15 additions & 4 deletions src/agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::region::RegionSelection;
use indexmap::IndexMap;
use serde::Deserialize;
use serde_string_enum::DeserializeLabeledStringEnum;
use std::collections::HashMap;
use std::collections::HashSet;
use std::rc::Rc;

Expand All @@ -15,6 +16,9 @@ define_id_type! {AgentID}
/// A map of [`Agent`]s, keyed by agent ID
pub type AgentMap = IndexMap<AgentID, Agent>;

/// A map of cost limits for an agent, keyed by year
pub type AgentCostLimitsMap = HashMap<u32, AgentCostLimits>;

/// An agent in the simulation
#[derive(Debug, Clone, PartialEq)]
pub struct Agent {
Expand All @@ -28,17 +32,24 @@ pub struct Agent {
pub search_space: Vec<AgentSearchSpace>,
/// The decision rule that the agent uses to decide investment.
pub decision_rule: DecisionRule,
/// The maximum capital cost the agent will pay.
pub capex_limit: Option<f64>,
/// The maximum annual operating cost (fuel plus var_opex etc) that the agent will pay.
pub annual_cost_limit: Option<f64>,
/// Cost limits (e.g. capital cost, annual operating cost)
pub cost_limits: AgentCostLimitsMap,
/// The regions in which this agent operates.
pub regions: RegionSelection,
/// The agent's objectives.
pub objectives: Vec<AgentObjective>,
}
define_id_getter! {Agent, AgentID}

/// The cost limits for an agent in a particular year
#[derive(Debug, Clone, PartialEq)]
pub struct AgentCostLimits {
/// The maximum capital cost the agent will pay.
pub capex_limit: Option<f64>,
/// The maximum annual operating cost (fuel plus var_opex etc) that the agent will pay.
pub annual_cost_limit: Option<f64>,
}

/// Which processes apply to this agent
#[derive(Debug, Clone, PartialEq)]
pub enum SearchSpace {
Expand Down
26 changes: 9 additions & 17 deletions src/input/agent.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Code for reading in agent-related data from CSV files.
use super::*;
use crate::agent::{Agent, AgentID, AgentMap, DecisionRule};
use crate::agent::{Agent, AgentCostLimitsMap, AgentID, AgentMap, DecisionRule};
use crate::commodity::CommodityMap;
use crate::process::ProcessMap;
use crate::region::{RegionID, RegionSelection};
Expand All @@ -17,6 +17,8 @@ mod search_space;
use search_space::read_agent_search_space;
mod commodity;
use commodity::read_agent_commodities;
mod cost_limit;
use cost_limit::read_agent_cost_limits;

const AGENT_FILE_NAME: &str = "agents.csv";

Expand All @@ -29,10 +31,6 @@ struct AgentRaw {
description: String,
/// The decision rule that the agent uses to decide investment.
decision_rule: String,
/// The maximum capital cost the agent will pay.
capex_limit: Option<f64>,
/// The maximum annual operating cost (fuel plus var_opex etc) that the agent will pay.
annual_cost_limit: Option<f64>,
/// The tolerance around the main objective to consider secondary objectives.
decision_lexico_tolerance: Option<f64>,
}
Expand Down Expand Up @@ -71,6 +69,7 @@ pub fn read_agents(
)?;
let mut agent_commodities =
read_agent_commodities(model_dir, &agents, commodities, region_ids, milestone_years)?;
let mut cost_limits = read_agent_cost_limits(model_dir, &agent_ids, milestone_years)?;

for (id, agent) in agents.iter_mut() {
agent.regions = agent_regions.remove(id).unwrap();
Expand All @@ -79,6 +78,9 @@ pub fn read_agents(
agent.search_space = search_space;
}
agent.commodities = agent_commodities.remove(id).unwrap();
if let Some(cost_limits) = cost_limits.remove(id) {
agent.cost_limits = cost_limits;
}
}

Ok(agents)
Expand Down Expand Up @@ -132,8 +134,7 @@ where
commodities: Vec::new(),
search_space: Vec::new(),
decision_rule,
capex_limit: agent_raw.capex_limit,
annual_cost_limit: agent_raw.annual_cost_limit,
cost_limits: AgentCostLimitsMap::new(),
regions: RegionSelection::default(),
objectives: Vec::new(),
};
Expand Down Expand Up @@ -161,8 +162,6 @@ mod tests {
id: "agent".into(),
description: "".into(),
decision_rule: "single".into(),
capex_limit: None,
annual_cost_limit: None,
decision_lexico_tolerance: None,
};
let agent_out = Agent {
Expand All @@ -171,8 +170,7 @@ mod tests {
commodities: Vec::new(),
search_space: Vec::new(),
decision_rule: DecisionRule::Single,
capex_limit: None,
annual_cost_limit: None,
cost_limits: AgentCostLimitsMap::new(),
regions: RegionSelection::default(),
objectives: Vec::new(),
};
Expand All @@ -186,16 +184,12 @@ mod tests {
id: "agent".into(),
description: "".into(),
decision_rule: "single".into(),
capex_limit: None,
annual_cost_limit: None,
decision_lexico_tolerance: None,
},
AgentRaw {
id: "agent".into(),
description: "".into(),
decision_rule: "single".into(),
capex_limit: None,
annual_cost_limit: None,
decision_lexico_tolerance: None,
},
];
Expand All @@ -206,8 +200,6 @@ mod tests {
id: "agent".into(),
description: "".into(),
decision_rule: "lexico".into(),
capex_limit: None,
annual_cost_limit: None,
decision_lexico_tolerance: None,
};
assert!(read_agents_file_from_iter(iter::once(agent)).is_err());
Expand Down
11 changes: 5 additions & 6 deletions src/input/agent/commodity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ impl AgentCommodityRaw {
}
}

/// Read agent objective info from the agent_commodities.csv file.
/// Read agent commodities info from the agent_commodities.csv file.
///
/// # Arguments
///
Expand Down Expand Up @@ -207,7 +207,7 @@ fn validate_agent_commodities(
#[cfg(test)]
mod tests {
use super::*;
use crate::agent::{Agent, DecisionRule};
use crate::agent::{Agent, AgentCostLimitsMap, DecisionRule};
use crate::commodity::{Commodity, CommodityCostMap, CommodityID, CommodityType, DemandMap};
use crate::region::RegionSelection;
use crate::time_slice::TimeSliceLevel;
Expand All @@ -216,7 +216,7 @@ mod tests {

#[test]
fn test_agent_commodity_raw_to_agent_commodity() {
let milestone_years = vec![2020, 2021, 2022];
let milestone_years = [2020, 2021, 2022];
let commodity = Rc::new(Commodity {
id: "commodity1".into(),
description: "A commodity".into(),
Expand Down Expand Up @@ -271,8 +271,7 @@ mod tests {
commodities: Vec::new(),
search_space: Vec::new(),
decision_rule: DecisionRule::Single,
capex_limit: None,
annual_cost_limit: None,
cost_limits: AgentCostLimitsMap::new(),
regions: RegionSelection::default(),
objectives: Vec::new(),
},
Expand All @@ -289,7 +288,7 @@ mod tests {
}),
)]);
let region_ids = HashSet::from([RegionID::new("region1")]);
let milestone_years = vec![2020];
let milestone_years = [2020];

// Valid case
let agent_commodity = AgentCommodity {
Expand Down
Loading