Skip to content
Draft
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
9 changes: 5 additions & 4 deletions src/asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ impl Asset {
// The cost for all commodity flows (including levies/incentives)
let flows_cost = self
.iter_flows()
.map(|flow| flow.get_total_cost_per_activity(&self.region_id, year, time_slice))
.map(|flow| flow.get_total_cost_per_activity(&flow.region_id, year, time_slice))
.sum();

self.process_parameter.variable_operating_cost + flows_cost
Expand Down Expand Up @@ -504,7 +504,7 @@ impl Asset {
.map(|flow| {
flow.coeff
* prices
.get(&flow.commodity.id, &self.region_id, time_slice)
.get(&flow.commodity.id, &flow.region_id, time_slice)
.unwrap_or(MoneyPerFlow(0.0))
})
.sum()
Expand Down Expand Up @@ -534,7 +534,7 @@ impl Asset {
let flow_costs = self
.iter_flows()
.filter(excludes_sed_svd_output)
.map(|flow| flow.get_total_cost_per_activity(&self.region_id, year, time_slice))
.map(|flow| flow.get_total_cost_per_activity(&flow.region_id, year, time_slice))
.sum();

cost_of_inputs + flow_costs + self.process_parameter.variable_operating_cost
Expand Down Expand Up @@ -583,7 +583,7 @@ impl Asset {
Box::new(output_flows_iter.map(move |flow| {
// Get the costs for this specific commodity flow
let commodity_specific_costs_per_flow =
flow.get_total_cost_per_flow(&self.region_id, year, time_slice);
flow.get_total_cost_per_flow(&flow.region_id, year, time_slice);

// Add these to the generic costs to get total cost for this commodity
let marginal_cost = generic_cost_per_flow + commodity_specific_costs_per_flow;
Expand Down Expand Up @@ -1293,6 +1293,7 @@ mod tests {
let commodity_rc = Rc::new(svd_commodity);
let process_flow = ProcessFlow {
commodity: Rc::clone(&commodity_rc),
region_id: region_id.clone(),
coeff: FlowPerActivity(-2.0), // Input
kind: FlowType::Fixed,
cost: MoneyPerFlow(0.0),
Expand Down
18 changes: 9 additions & 9 deletions src/input/process/flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,23 +184,22 @@ where
.get(record.commodity_id.as_str())
.with_context(|| format!("{} is not a valid commodity ID", &record.commodity_id))?;

// Create ProcessFlow object
let process_flow = ProcessFlow {
commodity: Rc::clone(commodity),
coeff: record.coeff,
kind: FlowType::Fixed,
cost: record.cost.unwrap_or(MoneyPerFlow(0.0)),
};

// Insert flow into the map
let region_year_map = flows_map.entry(id.clone()).or_default();
for (year, region_id) in iproduct!(record_years, record_regions.iter()) {
let process_flow = ProcessFlow {
commodity: Rc::clone(commodity),
region_id: region_id.clone(),
coeff: record.coeff,
kind: FlowType::Fixed,
cost: record.cost.unwrap_or(MoneyPerFlow(0.0)),
};
let flows_map = region_year_map
.entry((region_id.clone(), year))
.or_default();
let existing = Rc::get_mut(flows_map)
.unwrap() // safe: there will only be one copy
.insert(commodity.id.clone(), process_flow.clone())
.insert(commodity.id.clone(), process_flow)
.is_some();
ensure!(
!existing,
Expand Down Expand Up @@ -412,6 +411,7 @@ mod tests {
fn flow(commodity: Rc<Commodity>, coeff: f64) -> ProcessFlow {
ProcessFlow {
commodity,
region_id: "GBR".into(),
coeff: FlowPerActivity(coeff),
kind: FlowType::Fixed,
cost: MoneyPerFlow(0.0),
Expand Down
24 changes: 21 additions & 3 deletions src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,8 @@ impl ActivityLimits {
pub struct ProcessFlow {
/// The commodity produced or consumed by this flow
pub commodity: Rc<Commodity>,
/// The region in which this flow occurs
pub region_id: RegionID,
/// Maximum annual commodity flow quantity relative to other commodity flows.
///
/// Positive value indicates flow out and negative value indicates flow in.
Expand Down Expand Up @@ -674,7 +676,7 @@ mod tests {
}

#[fixture]
fn flow_with_cost() -> ProcessFlow {
fn flow_with_cost(region_id: RegionID) -> ProcessFlow {
ProcessFlow {
commodity: Rc::new(Commodity {
id: "test_commodity".into(),
Expand All @@ -687,6 +689,7 @@ mod tests {
demand: DemandMap::new(),
units: "PJ".into(),
}),
region_id,
coeff: FlowPerActivity(1.0),
kind: FlowType::Fixed,
cost: MoneyPerFlow(5.0),
Expand All @@ -696,7 +699,7 @@ mod tests {
#[fixture]
fn flow_with_cost_and_levy(region_id: RegionID, time_slice: TimeSliceID) -> ProcessFlow {
let mut levies = CommodityLevyMap::new();
levies.insert((region_id, 2020, time_slice), MoneyPerFlow(10.0));
levies.insert((region_id.clone(), 2020, time_slice), MoneyPerFlow(10.0));

ProcessFlow {
commodity: Rc::new(Commodity {
Expand All @@ -710,6 +713,7 @@ mod tests {
demand: DemandMap::new(),
units: "PJ".into(),
}),
region_id,
coeff: FlowPerActivity(1.0),
kind: FlowType::Fixed,
cost: MoneyPerFlow(5.0),
Expand All @@ -719,7 +723,7 @@ mod tests {
#[fixture]
fn flow_with_cost_and_incentive(region_id: RegionID, time_slice: TimeSliceID) -> ProcessFlow {
let mut levies = CommodityLevyMap::new();
levies.insert((region_id, 2020, time_slice), MoneyPerFlow(-3.0));
levies.insert((region_id.clone(), 2020, time_slice), MoneyPerFlow(-3.0));

ProcessFlow {
commodity: Rc::new(Commodity {
Expand All @@ -733,6 +737,7 @@ mod tests {
demand: DemandMap::new(),
units: "PJ".into(),
}),
region_id,
coeff: FlowPerActivity(1.0),
kind: FlowType::Fixed,
cost: MoneyPerFlow(5.0),
Expand All @@ -747,6 +752,7 @@ mod tests {
) {
let flow = ProcessFlow {
commodity: commodity_no_levies,
region_id: region_id.clone(),
coeff: FlowPerActivity(1.0),
kind: FlowType::Fixed,
cost: MoneyPerFlow(0.0),
Expand All @@ -766,6 +772,7 @@ mod tests {
) {
let flow = ProcessFlow {
commodity: commodity_with_levy,
region_id: region_id.clone(),
coeff: FlowPerActivity(1.0),
kind: FlowType::Fixed,
cost: MoneyPerFlow(0.0),
Expand All @@ -785,6 +792,7 @@ mod tests {
) {
let flow = ProcessFlow {
commodity: commodity_with_incentive,
region_id: region_id.clone(),
coeff: FlowPerActivity(1.0),
kind: FlowType::Fixed,
cost: MoneyPerFlow(0.0),
Expand All @@ -800,6 +808,7 @@ mod tests {
fn get_levy_different_region(commodity_with_levy: Rc<Commodity>, time_slice: TimeSliceID) {
let flow = ProcessFlow {
commodity: commodity_with_levy,
region_id: "GBR".into(),
coeff: FlowPerActivity(1.0),
kind: FlowType::Fixed,
cost: MoneyPerFlow(0.0),
Expand All @@ -819,6 +828,7 @@ mod tests {
) {
let flow = ProcessFlow {
commodity: commodity_with_levy,
region_id: region_id.clone(),
coeff: FlowPerActivity(1.0),
kind: FlowType::Fixed,
cost: MoneyPerFlow(0.0),
Expand All @@ -834,6 +844,7 @@ mod tests {
fn get_levy_different_time_slice(commodity_with_levy: Rc<Commodity>, region_id: RegionID) {
let flow = ProcessFlow {
commodity: commodity_with_levy,
region_id: region_id.clone(),
coeff: FlowPerActivity(1.0),
kind: FlowType::Fixed,
cost: MoneyPerFlow(0.0),
Expand All @@ -858,6 +869,7 @@ mod tests {
) {
let flow = ProcessFlow {
commodity: commodity_with_consumption_levy,
region_id: region_id.clone(),
coeff: FlowPerActivity(1.0), // Positive coefficient means production
kind: FlowType::Fixed,
cost: MoneyPerFlow(0.0),
Expand All @@ -877,6 +889,7 @@ mod tests {
) {
let flow = ProcessFlow {
commodity: commodity_with_consumption_levy,
region_id: region_id.clone(),
coeff: FlowPerActivity(-1.0), // Negative coefficient means consumption
kind: FlowType::Fixed,
cost: MoneyPerFlow(0.0),
Expand All @@ -896,6 +909,7 @@ mod tests {
) {
let flow = ProcessFlow {
commodity: commodity_with_production_levy,
region_id: region_id.clone(),
coeff: FlowPerActivity(1.0), // Positive coefficient means production
kind: FlowType::Fixed,
cost: MoneyPerFlow(0.0),
Expand All @@ -915,6 +929,7 @@ mod tests {
) {
let flow = ProcessFlow {
commodity: commodity_with_production_levy,
region_id: region_id.clone(),
coeff: FlowPerActivity(-1.0), // Negative coefficient means consumption
kind: FlowType::Fixed,
cost: MoneyPerFlow(0.0),
Expand Down Expand Up @@ -1004,18 +1019,21 @@ mod tests {

let flow_in = ProcessFlow {
commodity: Rc::clone(&commodity),
region_id: "GBR".into(),
coeff: FlowPerActivity(-1.0),
kind: FlowType::Fixed,
cost: MoneyPerFlow(0.0),
};
let flow_out = ProcessFlow {
commodity: Rc::clone(&commodity),
region_id: "GBR".into(),
coeff: FlowPerActivity(1.0),
kind: FlowType::Fixed,
cost: MoneyPerFlow(0.0),
};
let flow_zero = ProcessFlow {
commodity: Rc::clone(&commodity),
region_id: "GBR".into(),
coeff: FlowPerActivity(0.0),
kind: FlowType::Fixed,
cost: MoneyPerFlow(0.0),
Expand Down
2 changes: 2 additions & 0 deletions src/simulation/investment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -943,6 +943,7 @@ mod tests {
let commodity_rc = Rc::new(svd_commodity);
let process_flow = ProcessFlow {
commodity: Rc::clone(&commodity_rc),
region_id: "GBR".into(),
coeff: FlowPerActivity(2.0), // 2 units of flow per unit of activity
kind: FlowType::Fixed,
cost: MoneyPerFlow(0.0),
Expand Down Expand Up @@ -979,6 +980,7 @@ mod tests {
let commodity_rc = Rc::new(svd_commodity);
let process_flow = ProcessFlow {
commodity: Rc::clone(&commodity_rc),
region_id: "GBR".into(),
coeff: FlowPerActivity(1.0), // 1 unit of flow per unit of activity
kind: FlowType::Fixed,
cost: MoneyPerFlow(0.0),
Expand Down
12 changes: 6 additions & 6 deletions src/simulation/optimisation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ fn create_flow_map<'a>(
let flow_key = (
asset.clone(),
flow.commodity.id.clone(),
asset.region_id().clone(),
flow.region_id.clone(),
time_slice.clone(),
);
let flow_value = activity * flow.coeff / n_units;
Expand All @@ -207,19 +207,19 @@ fn create_flow_map<'a>(
// Copy flows for each child asset
for asset in existing_assets {
if let Some(parent) = asset.parent() {
for commodity_id in asset.iter_flows().map(|flow| &flow.commodity.id) {
for asset_flow in asset.iter_flows() {
for time_slice in time_slice_info.iter_ids() {
let flow = flows[&(
parent.clone(),
commodity_id.clone(),
parent.region_id().clone(),
asset_flow.commodity.id.clone(),
asset_flow.region_id.clone(),
time_slice.clone(),
)];
flows.insert(
(
asset.clone(),
commodity_id.clone(),
asset.region_id().clone(),
asset_flow.commodity.id.clone(),
asset_flow.region_id.clone(),
time_slice.clone(),
),
flow,
Expand Down
42 changes: 33 additions & 9 deletions src/simulation/prices.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1166,9 +1166,15 @@ mod tests {
use std::collections::{HashMap, HashSet};
use std::rc::Rc;

fn build_process_flow(commodity: &Commodity, coeff: f64, cost: MoneyPerFlow) -> ProcessFlow {
fn build_process_flow(
commodity: &Commodity,
coeff: f64,
cost: MoneyPerFlow,
region_id: &RegionID,
) -> ProcessFlow {
ProcessFlow {
commodity: Rc::new(commodity.clone()),
region_id: region_id.clone(),
coeff: FlowPerActivity(coeff),
kind: FlowType::Fixed,
cost,
Expand Down Expand Up @@ -1307,11 +1313,20 @@ mod tests {
let mut flows = IndexMap::new();
flows.insert(
a.id.clone(),
build_process_flow(&a, -1.0, MoneyPerFlow(0.0)),
build_process_flow(&a, -1.0, MoneyPerFlow(0.0), &region_id),
);
flows.insert(
b.id.clone(),
build_process_flow(&b, 1.0, MoneyPerFlow(0.0), &region_id),
);
flows.insert(
c.id.clone(),
build_process_flow(&c, 2.0, MoneyPerFlow(3.0), &region_id),
);
flows.insert(
d.id.clone(),
build_process_flow(&d, 1.0, MoneyPerFlow(4.0), &region_id),
);
flows.insert(b.id.clone(), build_process_flow(&b, 1.0, MoneyPerFlow(0.0)));
flows.insert(c.id.clone(), build_process_flow(&c, 2.0, MoneyPerFlow(3.0)));
flows.insert(d.id.clone(), build_process_flow(&d, 1.0, MoneyPerFlow(4.0)));

let process = build_process(
flows,
Expand Down Expand Up @@ -1390,11 +1405,20 @@ mod tests {
let mut flows = IndexMap::new();
flows.insert(
a.id.clone(),
build_process_flow(&a, -1.0, MoneyPerFlow(0.0)),
build_process_flow(&a, -1.0, MoneyPerFlow(0.0), &region_id),
);
flows.insert(
b.id.clone(),
build_process_flow(&b, 1.0, MoneyPerFlow(0.0), &region_id),
);
flows.insert(
c.id.clone(),
build_process_flow(&c, 2.0, MoneyPerFlow(3.0), &region_id),
);
flows.insert(
d.id.clone(),
build_process_flow(&d, 1.0, MoneyPerFlow(4.0), &region_id),
);
flows.insert(b.id.clone(), build_process_flow(&b, 1.0, MoneyPerFlow(0.0)));
flows.insert(c.id.clone(), build_process_flow(&c, 2.0, MoneyPerFlow(3.0)));
flows.insert(d.id.clone(), build_process_flow(&d, 1.0, MoneyPerFlow(4.0)));

let process = build_process(
flows,
Expand Down
Loading