Commit 195f863a authored by Niina Helistö's avatar Niina Helistö
Browse files

Merge branch 'dev' into #121_domain_checking

parents 3eaefe92 419bc30a
......@@ -5,6 +5,9 @@
* Output file streams
file f_changes /'output\changes.inc'/;
f_changes.lw = 26; // Field width of set label output, default in GAMS is 12, increase as needed
f_changes.pw = 500; // Number of characters that may be placed on a single row of the page, default in GAMS is 255, increase as needed
put f_changes
* Do not allow investments in the child setups
......@@ -22,6 +25,18 @@ loop(gnu(grid, node, unit)${r_invest(unit)},
tmp = round(r_invest(unit), 0) * p_gnu(grid, node, unit, 'unitSize');
put "p_gnu('", grid.tl, "', '", node.tl, "', '", unit.tl, "', 'capacity') = p_gnu('", grid.tl, "', '", node.tl, "', '", unit.tl, "', 'capacity') + ", tmp, ";"/;);
* Example updates for storage units (commented out at the moment, use names etc. that work in your case)
*p_gnBoundaryPropertiesForStates('battery_grid', 'battery_node', 'upwardLimit', 'useConstant') = 1;
*p_gnBoundaryPropertiesForStates('battery_grid', 'battery_node', 'upwardLimit', 'multiplier') = 1;
*p_gnBoundaryPropertiesForStates('battery_grid', 'battery_node', 'upwardLimit', 'constant')
* = p_gnu('battery_grid', 'battery_node', 'battery_charge', 'upperLimitCapacityRatio') * p_gnu('battery_grid', 'battery_node', 'battery_charge', 'capacity');
*p_gnu('battery_grid', 'battery_node', 'battery_charge', 'upperLimitCapacityRatio') = 0;
*uGroup('battery_charge', 'battery_online_group1') = yes;
*uGroup('battery_discharge', 'battery_online_group1') = yes;
*p_groupPolicy('battery_online_group1', 'constrainedOnlineTotalMax') = p_unit('battery_charge', 'unitCount');
*p_groupPolicy3D('battery_online_group1', 'constrainedOnlineMultiplier', 'battery_charge') = 1;
*p_groupPolicy3D('battery_online_group1', 'constrainedOnlineMultiplier', 'battery_discharge') = 1;
* Do not allow investments in the child setups (commented out at the moment)
*loop(gn2n_directional(grid, node, node_),
* put "p_gnn('", grid.tl, "', '", node.tl, "', '", node_.tl, "', 'transferCapMax') = 0;"/;
......
......@@ -59,7 +59,10 @@ GAMS command line arguments
--output_dir=<path>
Directory to write output to. Defaults to './output'.
--output_file=<filename.gdx>
Filename of the results file. Defaults to 'results.gdx'
References
----------
[1] N. Helist et al., Backbone---An Adaptable Energy Systems Modelling Framework,
......@@ -162,7 +165,9 @@ $include 'inc/4c_outputQuickFile.gms'
* Post-process results
$if exist '%input_dir%/4d_postProcess.gms' $include '%input_dir%/4d_postProcess.gms'
execute_unload '%output_dir%/results.gdx',
$if not set output_file $setglobal output_file 'results.gdx'
execute_unload '%output_dir%/%output_file%',
$$include 'defOutput/resultSymbols.inc'
;
......
set
s "Samples from historical periods" / s000 * s010 /
f "Forecasts for the short term" / f00 * f20 /
scenario /scen01*scen10/
up_down /up, down/
input_output /input, output/
effLevel "Pre-defined levels for efficiency representation that can start from t_solve + x"
/ level1*level9 /
effSelector "Select equations and lambdas/slope for efficiency calculations"
/ lambda01*lambda12, directOff, directOnLP, directOnMIP , incHR/
;
execute_unload 'Backbone_base_sets.gdx';
......@@ -45,6 +45,28 @@ All notable changes to this project will be documented in this file.
- Limiting the provision of online reserve based on the online variable
- Sample probability bug from scenario reduction (probability of single scenario above one)
## 1.1.5 - 2020-11-28
### Fixed
- Long-term scenario data when using only one scenario
- Bug with scenario smooting which caused wrong values on later than first solve
## 1.1.4 - 2019-11-02
### Fixed
- Sample probability bug from scenario reduction
## 1.1.3 - 2019-10-24
### Changed
- Scenario reduction is done based on total available energy
## 1.1.2 - 2019-10-23
### Changed
- Maintain original scenario labels after reduction
## [1.1] - 2019-04-17
### Added
- New model setting 't_perfectForesight' tells the number of time steps (from
......
# Backbone
Backbone is a generic energy network optimization tool written in [GAMS](https://www.gams.com/). It has been designed to be highly adaptable in different dimensions: temporal, spatial, technology representation and market design. The model can represent stochastics with a [model predictive control method](https://doi.org/10.1016/j.automatica.2008.03.002), with short-term forecasts and longer-term statistical uncertainties. Backbone can support multiple different models due to the modifiable temporal structure and varying lengths of the time steps.
Backbone is a generic energy network optimization tool written in [GAMS](https://www.gams.com/). It has been designed to be highly adaptable in different dimensions: temporal, spatial, technology representation and market design. The model can represent stochastics with a [model predictive control method](https://doi.org/10.1016/j.automatica.2008.03.002), with short-term forecasts and longer-term statistical uncertainties. Backbone can support multiple different models (e.g. investment or unit commitment) due to the modifiable temporal structure and varying lengths of the time steps.
If you use Backbone in a published work, please cite the [following publication](https://doi.org/10.3390/en12173388), which describes the Backbone energy systems modelling framework.
## Getting Started
Make sure that you have [Git](https://git-scm.com/) version control system and a Git interface, such as [TortoiseGit](https://tortoisegit.org/) or [SourceTree](https://www.sourcetreeapp.com/), installed on your computer. You also need to have [GAMS](https://www.gams.com/) installed.
Make sure that you have [Git](https://git-scm.com/) version control system and a Git interface, such as [TortoiseGit](https://tortoisegit.org/) or [SourceTree](https://www.sourcetreeapp.com/), installed on your computer.
You also need to have [GAMS](https://www.gams.com/) version 24.0 or later installed.
In order to get a copy of the Backbone project, you need to clone it using Git. Copy and paste the URL of the original Backbone repository and select the directory where you want Backbone to be cloned. The URL of the original Backbone repository is https://gitlab.vtt.fi/backbone/backbone.
......
......@@ -83,6 +83,7 @@ Model building /
* q_capacityMargin
* q_constrainedCapMultiUnit
* q_emissioncap
* q_energyMax
* q_energyShareMax
* q_energyShareMin
* q_ReserveShareMax
......
......@@ -83,6 +83,7 @@ Model invest /
q_capacityMargin
q_constrainedCapMultiUnit
q_emissioncap
q_energyMax
q_energyShareMax
q_energyShareMin
q_ReserveShareMax
......
......@@ -49,6 +49,9 @@ if (mType('invest'),
ms_central('invest', s) = no;
// Define time span of samples
// For selecting the samples, see, for example, https://doi.org/10.1016/j.energy.2020.118585.
// The duration of the samples can be, for example, 1 day or 1 week (24 h or 168 h).
// The samples can have different durations.
msStart('invest', 's000') = 1;
msEnd('invest', 's000') = msStart('invest', 's000') + 168;
msStart('invest', 's001') = 1 + 18*168;
......@@ -56,15 +59,27 @@ if (mType('invest'),
msStart('invest', 's002') = 1 + 35*168;
msEnd('invest', 's002') = msStart('invest', 's002') + 168;
// Define the probability (weight) of samples
// Define the probability of samples
// Probabilities are 1 in deterministic model runs.
// It is also possible to include, for example, 3 samples from a cold year with a probability of 1/10
// and 3 samples from a normal year year with a probability of 9/10.
p_msProbability('invest', s) = 0;
p_msProbability('invest', 's000') = 1;
p_msProbability('invest', 's001') = 1;
p_msProbability('invest', 's002') = 1;
// Define the weight of samples
// Weights describe how many times the samples are repeated in order to get the (typically) annual results.
// For example, 3 samples with equal weights and with a duration of 1 week should be repeated 17.38 times in order
// to cover the 52.14 weeks of the year.
// Weights are used for scaling energy production and consumption results and for estimating node state evolution.
p_msWeight('invest', s) = 0;
p_msWeight('invest', 's000') = 8760/504;
p_msWeight('invest', 's001') = 8760/504;
p_msWeight('invest', 's002') = 8760/504;
p_msWeight('invest', 's000') = 8760/168/3;
p_msWeight('invest', 's001') = 8760/168/3;
p_msWeight('invest', 's002') = 8760/168/3;
// Define the weight of samples in the calculation of fixed costs
// The sum of p_msAnnuityWeight should be 1 over the samples belonging to the same year.
// The p_msAnnuityWeight parameter is used for describing which samples belong to the same year so that the model
// is able to calculate investment costs and fixed operation and maintenance costs once per year.
p_msAnnuityWeight('invest', s) = 0;
p_msAnnuityWeight('invest', 's000') = 1/3;
p_msAnnuityWeight('invest', 's001') = 1/3;
......@@ -129,7 +144,7 @@ if (mType('invest'),
mSettingsEff('invest', 'level1') = inf;
// Define the horizon when start-up and shutdown trajectories are considered
mSettings('invest', 't_trajectoryHorizon') = 8760;
mSettings('invest', 't_trajectoryHorizon') = 0;
* --- Define output settings for results --------------------------------------
......
......@@ -83,6 +83,7 @@ Model schedule /
q_capacityMargin
* q_constrainedCapMultiUnit
* q_emissioncap
* q_energyMax
* q_energyShareMax
* q_energyShareMin
q_ReserveShareMax
......
......@@ -140,6 +140,9 @@ if (mType('schedule'),
mf_realization('schedule', 'f00') = yes;
mf_central('schedule', f) = no;
mf_central('schedule', 'f02') = yes;
// Define special forecast label that holds scenario data
//mf_scenario('schedule', 'scen') = yes;
// Define forecast probabilities (weights)
p_mfProbability('schedule', f) = 0;
......
......@@ -19,6 +19,9 @@ $offtext
* --- Results Symbols Included in Output --------------------------------------
* =============================================================================
* --- Symbols related to the simulation setup ---------------------------------
t_realized = t
* --- Cost Result Symbols -----------------------------------------------------
// Total Objective Function
......@@ -124,6 +127,17 @@ r_uTotalOnlinePerUnit
r_uTotalStartup
r_uTotalShutdown
* --- Emissions Results -----------------------------------------------
// Unit level emissions
r_emissions
// Emission sums
r_nuTotalEmissions
r_nTotalEmissions
r_uTotalEmissions
r_totalEmissions
* --- Reserve Provision Result Symbols ----------------------------------------
// Reserve provision results required for model structure !!!!!!!!!!!!!!!!!!!!!
......
......@@ -32,36 +32,36 @@ Sets
mSetting "setting categories for models" /
// General Time Structure
t_start, // First time step for the start of simulation
t_jump, // Number of time steps realized with each solve
t_horizon, // Length of the simulation horizon in time steps (central forecast)
t_end, // Last time step of the simulation
loadPoint, // Load advanced basis; 0 = no basis, 1 = latest solve, 2 = all solves, 3 = first solve
savePoint, // Save advanced basis; 0 = no basis, 1 = latest solve, 2 = all solves, 3 = first solve
lastStepInIntervalBlock, // Last time step in the block of intervals with the same length
stepsPerInterval, // Number of time steps aggregated within interval
stepLengthInHours, // Length of one time step in hours
t_start "First time step for the start of simulation"
t_jump "Number of time steps realized with each solve"
t_horizon "Length of the simulation horizon in time steps (central forecast)"
t_end "Last time step of the simulation"
loadPoint "Load advanced basis; 0 = no basis, 1 = latest solve, 2 = all solves, 3 = first solve"
savePoint "Save advanced basis; 0 = no basis, 1 = latest solve, 2 = all solves, 3 = first solve"
lastStepInIntervalBlock "Last time step in the block of intervals with the same length"
stepsPerInterval "Number of time steps aggregated within interval"
stepLengthInHours "Length of a time step in hours"
// Samples and Forecasts
samples, // Number of active samples
forecasts, // Number of active forecasts
t_forecastLengthUnchanging, // Length of forecasts in time steps - this does not decrease when the solve moves forward (requires forecast data that is longer than the horizon at first)
t_forecastLengthDecreasesFrom, // Length of forecasts in time steps - this decreases when the solve moves forward until the new forecast data is read (then extends back to full length)
t_forecastStart, // Time step for first reading the forecasts (not necessarily t_start)
t_forecastJump, // Number of time steps between each update of the forecasts
samples "Number of active samples"
forecasts "Number of active forecasts"
t_forecastLengthUnchanging "Length of forecasts in time steps - this does not decrease when the solve moves forward (requires forecast data that is longer than the horizon at first)"
t_forecastLengthDecreasesFrom "Length of forecasts in time steps - this decreases when the solve moves forward until the new forecast data is read (then extends back to full length)"
t_forecastStart "Time step for first reading the forecasts (not necessarily t_start)"
t_forecastJump "Number of time steps between each update of the forecasts"
t_improveForecast "Number of time steps ahead of time on which the forecast is improved on each solve"
t_perfectForesight "Number of time steps for which realized data is used instead of forecasts"
onlyExistingForecasts "Use only existing forecast values when reading updated forecasts. Note: zero values need to be saved as Eps in the gdx file."
scenarios "Number of long-term scenarios used"
scenarioLength "Length of scenario in time steps for creating stocahstic scenarios from time series data"
scenarioLength "Length of scenario in time steps for creating stochastic scenarios from time series data"
// Features
t_trajectoryHorizon, // Length of the horizon when start-up and shutdown trajectories are considered (in time steps)
t_initializationPeriod, // Number of time steps in the beginning of the simulation which are solved but the results of which are not stored
dataLength, // The maximum number of time steps in any input data time series (recommended for correctly circulating data)
red_num_leaves "Desired number of preserved scenarios or leaves (SCENRED)"
t_trajectoryHorizon "Length of the horizon when start-up and shutdown trajectories are considered (in time steps)"
t_initializationPeriod "Number of time steps in the beginning of the simulation which are solved but the results of which are not stored"
dataLength "The maximum number of time steps in any input data time series (recommended for correctly circulating data)"
red_num_leaves "Desired number of preserved scenarios or leaves of scenario reduction (SCENRED)"
red_percentage "Desired relative distance (accuracy) of scenario reduction (SCENRED)"
incHRAdditionalConstraints // Method to include the two additional constraints for incremental heat rates;
incHRAdditionalConstraints "Method to include the two additional constraints for incremental heat rates"
// 0 = include for units with non-convex fuel use, 1 = include for all units
/
......@@ -226,11 +226,11 @@ param_gn "Possible parameters for grid, node" /
/
param_gnBoundaryTypes "Types of boundaries that can be set for a node with a state variable" /
upwardLimit "Absolute maximum state of the node (unit depends on energyCapacity)"
downwardLimit "Absolute minimum energy in the node (unit depends on energyCapacity)"
upwardSlack01*upwardSlack20 "A threshold after which a specific cost co-efficient is applied (unit depends on energyCapacity)"
downwardSlack01*downwardSlack20 "A threshold after which a specific cost co-efficient is applied (unit depends on energyCapacity)"
reference "Reference value for a state that can be used to bound a state (unit depends on energyCapacity)"
upwardLimit "Absolute maximum state of the node (unit of measure depends on energyStoredPerUnitOfState)"
downwardLimit "Absolute minimum energy in the node (unit of measure depends on energyStoredPerUnitOfState)"
upwardSlack01*upwardSlack20 "A threshold after which a specific cost co-efficient is applied (unit of measure depends on energyStoredPerUnitOfState)"
downwardSlack01*downwardSlack20 "A threshold after which a specific cost co-efficient is applied (unit of measure depends on energyStoredPerUnitOfState)"
reference "Reference value for a state that can be used to bound a state (unit of measure depends on energyStoredPerUnitOfState)"
maxSpill "Maximum spill rate from the node (MWh/h)"
minSpill "Minimum spill rate from the node (MWh/h)"
balancePenalty "Penalty value for violating the energy balance of that particular node (EUR/MWh) (can be interpretated as the energy price in certain settings)"
......@@ -252,7 +252,7 @@ param_gnn "Set of possible data parameters for grid, node, node (nodal interconn
diffCoeff "Coefficients for energy diffusion between nodes (MW/[v_state])"
boundStateMaxDiff "Maximum difference of node state pairs ([v_state])"
transferCapInvLimit "Capacity limit for investments (MW)"
investMIP "A flag to make integer investment instead of continous investment (MW versus number of links)"
investMIP "A flag to make integer investment instead of continuous investment (MW versus number of links)"
unitSize "Size of one link for integer investments (MW)"
invCost "Investment cost (EUR/MW)"
annuity "Investment annuity"
......@@ -317,7 +317,6 @@ param_unit "Set of possible data parameters for units" /
hrop00 * hrop12 "Right border of the incremental heat rates"
section "Possibility to define a no load fuel use for units with zero minimum output"
hrsection "no load fuel use to be defined when using incremental heat rates"
level1 * level9 "Level of simplification in the part-load efficiency representation"
useTimeseries "A flag to use time series form input for unit parameters whenever possible"
investMIP "A flag to make integer investment instead of continous investment"
maxUnitCount "Maximum number of units when making integer investments"
......@@ -354,6 +353,8 @@ param_policy "Set of possible data parameters for groups or grid, node, regulati
emissionTax "Emission tax (EUR/tonne)"
emissionCap "Emission limit (tonne)"
instantaneousShareMax "Maximum instantaneous share of generation and import from a particular group of units and transfer links"
energyMax "Maximum energy production or consumption from a particular group of units over samples"
energyMaxVgenSign "Sign for v_gen in the maximum energy constraint - use -1 when you need a minimum energy constraint (then also energyMax should be negative)"
energyShareMax "Maximum energy share of generation from a particular group of units"
energyShareMin "Minimum energy share of generation from a particular group of units"
constrainedCapMultiplier "Multiplier a(i) for unit investments in equation Sum(i, a(i)*v_invest(i)) <= b"
......
......@@ -41,7 +41,7 @@ Sets
unit_slope(unit) "Units with piecewise linear efficiency constraints"
unit_noSlope(unit) "Units without piecewise linear efficiency constraints"
unitAggregator_unit(unit, unit) "Aggregate unit linked to aggregated units"
unitUnitEffLevel(unit, unit, EffLevel) "Aggregator unit linke to aggreted units with a definition when to start the aggregation"
unitUnitEffLevel(unit, unit, EffLevel) "Aggregator unit linked to aggreted units with a definition when to start the aggregation"
flowUnit(flow, unit) "Units linked to a certain energy flow time series"
unitUnittype(unit, unittype) "Link generation technologies to types"
unitStarttype(unit, starttype) "Units with special startup properties"
......@@ -96,6 +96,7 @@ Sets
t_current(t) "Set of time steps within the current solve horizon"
t_active(t) "Set of active t:s within the current solve horizon, including necessary history"
t_invest(t) "Time steps when investments can be made"
t_realized(t) "Set of realized time steps in the simulation"
tt(t) "Temporary subset for time steps used for calculations"
tt_(t) "Another temporary subset for time steps used for calculations"
tt_block(counter, t) "Temporary time step subset for storing the time interval blocks"
......
......@@ -102,7 +102,7 @@ Parameters
Parameters
p_msWeight(mType, s) "Temporal weight of sample: number of similar periods represented by sample s"
p_msAnnuityWeight(mType, s) "Temporal weight of sample: used when calculating annuities"
p_msProbability(mType, s) "Probability to reach sample conditioned on anchestor samples"
p_msProbability(mType, s) "Probability to reach sample conditioned on ancestor samples"
p_mfProbability(mType, f) "Probability of forecast"
p_msft_probability(mType, s, f, t) "Probability of forecast"
p_sProbability(s) "Probability of sample"
......
......@@ -119,6 +119,19 @@ Parameters
r_gnTotalConsumptionShare(grid, node) "Total consumption gn/g share"
r_gTotalConsumption(grid) "Total consumption of energy in g over the simulation (MWh)"
* --- Emissions Results -------------------------------------------------------
// Unit level emissions
r_emissions (node, emission, unit, f, t) "Emissions from units (tCO2)"
// Emission sums
r_nuTotalEmissions (node, unit, emission) "Total emissions from units (tCO2)"
r_nTotalEmissions(node, emission) "Emissions in gn (tCO2)"
r_uTotalEmissions(unit, emission) "Emissions in gn (tCO2)"
r_totalEmissions (emission) "Summed emissions (tCO2)"
* --- Unit Online State Results -----------------------------------------------
// Online results required for model structure
......
......@@ -116,6 +116,7 @@ equations
q_capacityMargin(grid, node, s, f, t) "There needs to be enough capacity to cover energy demand plus a margin"
q_constrainedCapMultiUnit(group) "Constrained unit number ratios and sums for a group of units"
q_emissioncap(group, emission) "Limit for emissions"
q_energyMax(group) "Maximum energy production or consumption from a group of units"
q_energyShareMax(group) "Maximum energy share of generation and import from a group of units"
q_energyShareMin(group) "Minimum energy share of generation and import from a group of units"
q_ReserveShareMax(group, restype, up_down, group, s, f, t) "Maximum reserve share of a group of units"
......
......@@ -61,7 +61,7 @@ q_obj ..
+ sum(gn(grid, node),
+ vq_gen(inc_dec, grid, node, s, f, t)
*( PENALTY_BALANCE(grid, node)${not p_gnBoundaryPropertiesForStates(grid, node, 'balancePenalty', 'useTimeSeries')}
+ ts_node(grid, node, 'balancePenalty', f, t)${p_gnBoundaryPropertiesForStates(grid, node, 'balancePenalty', 'useTimeSeries')}
+ ts_node_(grid, node, 'balancePenalty', s, f, t)${p_gnBoundaryPropertiesForStates(grid, node, 'balancePenalty', 'useTimeSeries')}
)
) // END sum(gn)
) // END sum(inc_dec)
......
......@@ -2823,6 +2823,40 @@ q_emissioncap(group, emission)
+ p_groupPolicyEmission(group, 'emissionCap', emission)
;
*--- Maximum Energy -----------------------------------------------------------
q_energyMax(group)
${ p_groupPolicy(group, 'energyMax')
} ..
+ sum(msft(m, s, f, t)${sGroup(s, group)},
+ p_msft_Probability(m,s,f,t)
* p_stepLength(m, f, t)
* [
+ 1${not p_groupPolicy(group, 'energyMaxVgenSign')}
+ p_groupPolicy(group, 'energyMaxVgenSign') // Multiply by -1 in order to convert to minimum energy constraint
]
* [
// Production of units in the group
+ sum(gnu_output(grid, node, unit)${ gnuGroup(grid, node, unit, group)
and gnuft(grid, node, unit, f, t)
},
+ v_gen(grid, node, unit, s, f, t)
) // END sum(gnu)
// Consumption of units in the group
+ sum(gnu_input(grid, node, unit)${ gnuGroup(grid, node, unit, group)
and gnuft(grid, node, unit, f, t)
},
- v_gen(grid, node, unit, s, f, t)
) // END sum(gnu)
] // END * p_stepLength
) // END sum(msft)
=L=
+ p_groupPolicy(group, 'energyMax') // Use negative energyMax value if you need a "minimum energy" equation
;
*--- Maximum Energy Share -----------------------------------------------------
q_energyShareMax(group)
......
......@@ -41,6 +41,19 @@ loop(m,
and ord(t) <= mSettings(m, 't_end') + mSettings(m, 't_horizon')
}
= yes;
if(mSettings(m, 't_jump') > mSettings(m, 't_end'),
mSettings(m, 't_jump') = mSettings(m, 't_end');
put log "!!! t_jump was larger than t_end. t_jump was decreased to t_end."/
);
if(mod(mSettings(m, 't_end'), mSettings(m, 't_jump')) > 0,
abort "t_end is not divisible by t_jump";
);
// Calculate realized timesteps in the simulation
t_realized(t_full(t))${ ord(t) >= mSettings(m, 't_start') + 1
and ord(t) <= mSettings(m, 't_end') + 1
}
= yes;
* --- Samples and Forecasts ---------------------------------------------------
$ontext
......@@ -177,7 +190,7 @@ loop(m,
* --- Calculate 'lastStepNotAggregated' for aggregated units and aggregator units ---
loop(effLevel$mSettingsEff(m, effLevel),
loop(effLevel_${mSettingsEff(m, effLevel_) and ord(effLevel_) < ord(effLevel)},
loop(effLevel_${mSettingsEff(m, effLevel_) and ord(effLevel_) <= ord(effLevel)},
p_unit(unit_aggregated(unit), 'lastStepNotAggregated')${ sum(unit_,unitUnitEffLevel(unit_, unit, effLevel)) }
= mSettingsEff(m, effLevel_);
p_unit(unit_aggregator(unit), 'lastStepNotAggregated')${ sum(unit_,unitUnitEffLevel(unit, unit_, effLevel)) }
......
......@@ -124,6 +124,7 @@ Option clear = q_constrainedOnlineMultiUnit;
Option clear = q_capacityMargin;
Option clear = q_constrainedCapMultiUnit;
Option clear = q_emissioncap;
Option clear = q_energyMax;
Option clear = q_energyShareMax;
Option clear = q_energyShareMin;
Option clear = q_ReserveShareMax;
......@@ -466,7 +467,7 @@ loop(mf_realization(mSolve, f_),
);
// Central forecast for the long-term scenarios comes from a special forecast label
Option clear = df_scenario;
if(mSettings(mSolve, 'scenarios') > 1,
if(mSettings(mSolve, 'scenarios') >= 1,
loop((msft(ms_central(mSolve, s), f, t), mf_scenario(mSolve, f_)),
df_scenario(ft(f, t)) = ord(f_) - ord(f);
);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment