Skip to content
Open
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
29 changes: 25 additions & 4 deletions src/simulation/optimisation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,16 @@ impl Solution<'_> {
.capacity_vars
.keys()
.zip(self.solution.columns()[self.variables.capacity_var_idx.clone()].iter())
.map(|(asset, capacity)| (asset, Capacity(*capacity)))
.map(|(asset, capacity)| {
// If the asset is divisible, the capacity variable represents number of units,
// so convert to total capacity
let capacity_value = if let Some(unit_size) = asset.unit_size() {
capacity * unit_size.value()
} else {
*capacity
};
(asset, Capacity(capacity_value))
})
}

/// Keys and dual values for commodity balance constraints.
Expand Down Expand Up @@ -655,10 +664,22 @@ fn add_capacity_variables(
);

let current_capacity = asset.capacity().value();
let lower = ((1.0 - capacity_margin) * current_capacity).max(0.0);
let upper = (1.0 + capacity_margin) * current_capacity;
let coeff = calculate_capacity_coefficient(asset);
let var = problem.add_column(coeff.value(), lower..=upper);

let var = if let Some(unit_size) = asset.unit_size() {
// Divisible asset: capacity variable represents number of units
let unit_size_value = unit_size.value();
let current_units = current_capacity / unit_size_value;
let lower = ((1.0 - capacity_margin) * current_units).max(0.0);
let upper = (1.0 + capacity_margin) * current_units;
problem.add_integer_column(coeff.value() * unit_size_value, lower..=upper)
} else {
// Indivisible asset: capacity variable represents total capacity
let lower = ((1.0 - capacity_margin) * current_capacity).max(0.0);
let upper = (1.0 + capacity_margin) * current_capacity;
problem.add_column(coeff.value(), lower..=upper)
};

let existing = variables.insert(asset.clone(), var).is_some();
assert!(!existing, "Duplicate entry for var");
}
Expand Down
11 changes: 9 additions & 2 deletions src/simulation/optimisation/constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,15 @@ where
if let Some(&capacity_var) = capacity_vars.get(asset) {
// Asset with flexible capacity
for (ts_selection, limits) in asset.iter_activity_per_capacity_limits() {
let upper_limit = limits.end().value();
let lower_limit = limits.start().value();
let mut upper_limit = limits.end().value();
let mut lower_limit = limits.start().value();

// If the asset is divisible, the capacity variable represents number of units,
// so we need to multiply the per-capacity limits by the unit size.
if let Some(unit_size) = asset.unit_size() {
upper_limit *= unit_size.value();
lower_limit *= unit_size.value();
}

// Collect capacity and activity terms
// We have a single capacity term, and activity terms for all time slices in the selection
Expand Down