Commit 05eb6fe3 authored by Niina Helistö's avatar Niina Helistö
Browse files

Merge branch 'dev' into OfflineReserve

parents 5d9e7db7 9b60c287
......@@ -26,12 +26,11 @@ Created by:
Ran Li
Ciara O'Dwyer
- Based on Stochastic Model Predictive Control method [1].
- Enables multiple different models (m) to be implemented by changing
the temporal structure of the model. (MULTI-MODEL RUNS TO BE IMPLEMENTED)
This is a GAMS implementation of the Backbone energy system modelling framework
[1]. Features include:
- Based on Stochastic Model Predictive Control method [2].
- Time steps (t) can vary in length.
- Short term forecast stochasticity (f) and longer term statistical uncertainty (s).
- Can handle ramp based dispatch in addition to energy blocks. (TO BE IMPLEMENTED)
GAMS command line arguments
......@@ -63,7 +62,10 @@ GAMS command line arguments
References
----------
[1] K. Nolde, M. Uhr, and M. Morari, Medium term scheduling of a hydro-thermal
[1] N. Helist et al., Backbone---An Adaptable Energy Systems Modelling Framework,
Energies, vol. 12, no. 17, p. 3388, Sep. 2019. Available at:
https://dx.doi.org/10.3390/en12173388.
[2] K. Nolde, M. Uhr, and M. Morari, Medium term scheduling of a hydro-thermal
system using stochastic model predictive control, Automatica, vol. 44,
no. 6, pp. 15851594, Jun. 2008.
......@@ -126,7 +128,7 @@ $include '%input_dir%/modelsInit.gms'
* === Simulation ==============================================================
$include 'inc/3a_periodicInit.gms' // Initialize modelling loop
loop(modelSolves(mSolve, tSolve),
loop(modelSolves(mSolve, tSolve)$(execError = 0),
solveCount = solveCount + 1;
$$include 'inc/3b_periodicLoop.gms' // Update modelling loop
$$include 'inc/3c_inputsLoop.gms' // Read input data that is updated within the loop
......@@ -143,7 +145,6 @@ $ifthene.debug %debug%>1
$$include defOutput/debugSymbols.inc
;
$endif.debug
if(execError, put log "!!! Errors encountered: " execError:0:0);
);
$if exist '%input_dir%/3z_modelsClose.gms' $include '%input_dir%/3z_modelsClose.gms';
......@@ -164,6 +165,8 @@ execute_unload '%output_dir%/results.gdx',
$ife %debug%>0
execute_unload '%output_dir%/debug.gdx';
if(errorcount > 0, abort errorcount);
if(execError,
putclose log "!!! Errors encountered: " execError:0:0/;
abort "FAILED";
);
* === THE END =================================================================
......@@ -7,12 +7,15 @@ All notable changes to this project will be documented in this file.
- All input files, including *inputData.gdx*, are optional
- Enabling different combinations of LP and MIP online and invest variables
- Separate availability parameter for output units in the capacity margin constraint
- Parameter `gn_forecasts(*, node, timeseries)` to tell which nodes and timeseries use forecasts
### Changed
- Updated tool defintions for Sceleton Titan and Spine Toolbox
- The program will now stop looping in case of execution errors.
### Fixed
- Removed hard-coded `elec grids` from *setVariableLimits* and *rampSched files*
- Time series smooting not working at all (#100)
## [1.1] - 2019-04-17
### Added
......
# 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 [1], 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 due to the modifiable temporal structure and varying lengths of the time steps.
[1] Nolde, K., Uhr, M., & Morari, M. (2008). Medium term scheduling of a hydro-thermal system using stochastic model predictive control. Automatica, 1585-1594.
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
......@@ -10,7 +10,9 @@ Make sure that you have [Git](https://git-scm.com/) version control system and a
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.
You should now have *Backbone.gms*, a few additional files and three subdirectories in the directory where you cloned Backbone. Note that you need to manually create two additional subdirectories in order to get Backbone working. These subdirectories should be named *input* and *output* and they should be created in the same directory where *Backbone.gms* is.
You should now have *Backbone.gms*, a few additional files and five subdirectories in the directory where you cloned Backbone.
Small example input datasets are provided online in the [wiki](https://gitlab.vtt.fi/backbone/backbone/wikis/Example-data-sets).
## Model File Structure
......@@ -29,8 +31,8 @@ Backbone has been designed with a modular structure, making it easier to change
* 2d_constraints.gms - Contains definitions for constraint equations.
* *Model Definition Files* - Contains GAMS definitions for different models, essentially lists the equations (constraints) that apply. Current files include *schedule.gms*, *building.gms* and *invest.gms*.
* 3a_periodicInit.gms - Initializes various data and sets for the solve loop.
* 3b_inputsLoop.gms - Instructions for possible data import inside the solve loop, as well as forecast in-the-loop improvements.
* 3c_periodicLoop.gms - Contains instructions for the forecast-time structure of the desired model.
* 3b_periodicLoop.gms - Contains instructions for the forecast-interval structure of the desired model.
* 3c_inputsLoop.gms - Contains instructions for updating the forecast data, optional forecast improvements, aggregating time series data for the time intervals, and other input data processing.
* 3d_setVariableLimits.gms - Defines the variable boundaries for each solve.
* 3e_solve.gms - Contains the GAMS solve command for using the solver.
* 3f_afterSolve.gms - Fixes some variable values after solve.
......@@ -45,7 +47,7 @@ Most of these files are under *\inc* in the Backbone folder, except for the mode
* timeAndSamples.inc - Contains definitions for the time, forecast and sample index ranges.
* modelsInit.gms - Contains model parameters for the solve (or a link to a template under *\defModels* to be used). Useful for any additional GAMS scripting.
Backbone folder contains three template files *1_options_temp.gms*, *timeAndSamples_temp.inc*, and *modelsInit_temp.gms* to provide examples of the input format. These files can be copied into *\input* and renamed to *1_options.gms*, *timeAndSamples.inc*, and *modelsInit.gms*.
Backbone folder contains template files *1_options_temp.gms*, *timeAndSamples_temp.inc*, and *modelsInit_temp.gms* to provide examples of the input format. These files can be copied into *\input* and renamed to *1_options.gms*, *timeAndSamples.inc*, and *modelsInit.gms*.
## When Simply Using Backbone
......@@ -62,6 +64,9 @@ When starting to use Backbone, there is no immediate need to understand every si
* Erkka Rinne
* Topi Rasku
* Niina Helisto
* Dana Kirchem
* Ran Li
* Ciara O'Dwyer
## License
......
......@@ -54,6 +54,8 @@ if (mType('building'),
// Define the probability (weight) of samples
p_msProbability('building', s) = 0;
p_msProbability('building', 's000') = 1;
p_msWeight('building', s) = 0;
p_msWeight('building', 's000') = 1;
* --- Define Time Step Intervals ----------------------------------------------
......
......@@ -58,9 +58,13 @@ if (mType('invest'),
// Define the probability (weight) of samples
p_msProbability('invest', s) = 0;
p_msProbability('invest', 's000') = 8760/504;
p_msProbability('invest', 's001') = 8760/504;
p_msProbability('invest', 's002') = 8760/504;
p_msProbability('invest', 's000') = 1;
p_msProbability('invest', 's001') = 1;
p_msProbability('invest', 's002') = 1;
p_msWeight('invest', s) = 0;
p_msWeight('invest', 's000') = 8760/504;
p_msWeight('invest', 's001') = 8760/504;
p_msWeight('invest', 's002') = 8760/504;
* --- Define Time Step Intervals ----------------------------------------------
......@@ -78,6 +82,10 @@ if (mType('invest'),
// Define the number of forecasts used by the model
mSettings('invest', 'forecasts') = 0;
// Define which nodes and timeseries use forecasts
//Option clear = gn_forecasts; // By default includes everything, so clear first
//gn_forecasts('wind', 'XXX', 'ts_cf') = yes;
// Define forecast properties and features
mSettings('invest', 't_forecastStart') = 0; // At which time step the first forecast is available ( 1 = t000001 )
mSettings('invest', 't_forecastLengthUnchanging') = 0; // 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)
......
......@@ -64,6 +64,8 @@ if (mType('schedule'),
// Define the probability (weight) of samples
p_msProbability('schedule', s) = 0;
p_msProbability('schedule', 's000') = 1;
p_msWeight('schedule', s) = 0;
p_msWeight('schedule', 's000') = 1;
// If using long-term samples, uncomment
//ms_central('schedule', 's001') = yes;
......@@ -104,6 +106,10 @@ if (mType('schedule'),
// Define the number of forecasts used by the model
mSettings('schedule', 'forecasts') = 3;
// Define which nodes and timeseries use forecasts
//Option clear = gn_forecasts; // By default includes everything, so clear first
//gn_forecasts('wind', 'XXX', 'ts_cf') = yes;
// Define forecast properties and features
mSettings('schedule', 't_forecastStart') = 1; // At which time step the first forecast is available ( 1 = t000001 )
mSettings('schedule', 't_forecastLengthUnchanging') = 36; // 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)
......
......@@ -131,7 +131,8 @@ Sets
s_prev(s) "Temporary set for previous sample"
$if defined scenario
s_scenario(s, scenario) "Which samples belong to which scenarios"
gn_scenarios(*, node, *) "Which grid/flow, node and timeseries/param have data for long-term scenarios"
gn_forecasts(*, node, timeseries) "Which grid/flow, node and timeseries use short-term forecasts"
gn_scenarios(*, node, timeseries) "Which grid/flow, node and timeseries have data for long-term scenarios"
* --- Sets used for the changing unit aggregation and efficiency approximations
uft(unit, f, t) "Active units on intervals, enables aggregation of units for later intervals"
......
......@@ -17,7 +17,6 @@ $offtext
* --- Internal counters -------------------------------------------------------
Scalars
errorcount /0/
solveCount /0/
tSolveFirst "counter (ord) for the first t in the solve"
tSolveLast "counter for the last t in the solve"
......@@ -92,7 +91,7 @@ Parameters
* --- Probability -------------------------------------------------------------
Parameters
p_msWeight(mType, s) "Weight of sample"
p_msWeight(mType, s) "Temporal weight of sample: number of similar periods represented by sample s"
p_msProbability(mType, s) "Probability to reach sample conditioned on anchestor samples"
p_mfProbability(mType, f) "Probability of forecast"
p_msft_probability(mType, s, f, t) "Probability of forecast"
......@@ -126,6 +125,7 @@ Parameters
df_central(f, t) "Displacement needed to reach the central forecast - this is needed when the forecast tree gets reduced in dynamic equations"
df_reserves(node, restype, f, t) "Forecast index displacement needed to reach the realized forecast when committing reserves"
df_scenario(f, t) "Forecast index displacement needed to get central forecast data for long-term scenarios"
df_realization(f, t) "Displacement needed to reach the realized forecast on the current time step when no forecast is available"
// Sample displacement arrays
ds(s, t) "Displacement needed to reach the sample of previous time step"
......@@ -186,9 +186,6 @@ Parameters
p_tsMaxValue(*, node, timeseries) "Maximum allowed value of timeseries in grid/flow and node"
;
* Reset values for some parameters
Options clear = ts_influx_std, clear = ts_cf_std;
* --- Other time dependent parameters -----------------------------------------
Parameters
p_storageValue(grid, node, t) "Value of stored something at the end of a time step"
......
......@@ -594,10 +594,14 @@ loop( (nu(node, unit), restypeDirection(restype, up_down)),
* --- Default values ---------------------------------------------------------
* =============================================================================
loop(timeseries$(not sameas(timeseries, 'ts_cf')),
p_autocorrelation(gn, timeseries) = 0;
p_tsMinValue(gn, timeseries) = -Inf;
p_tsMaxValue(gn, timeseries) = Inf;
);
p_autocorrelation(flowNode, 'ts_cf') = 0;
p_tsMinValue(flowNode, 'ts_cf') = 0;
p_tsMaxValue(flowNode, 'ts_cf') = 1;
* By default all nodes use forecasts for all timeseries
gn_forecasts(gn, timeseries) = yes;
gn_forecasts(flowNode, timeseries) = yes;
gn_forecasts(restype, node, 'ts_reserveDemand') = yes;
......@@ -2274,7 +2274,7 @@ q_boundCyclic(gnss_bound(gn_state(grid, node), s_, s), m)
and tSolveFirst = mSettings(m, 't_start')
}..
// Initial value of the state of the node at the start of the sample
// Initial value of the state of the node at the start of the sample s
+ sum(mst_start(m, s, t),
+ sum(sft(s, f, t),
+ v_state(grid, node, s, f+df(f,t+dt(t)), t+dt(t))
......@@ -2283,12 +2283,28 @@ q_boundCyclic(gnss_bound(gn_state(grid, node), s_, s), m)
=E=
// State of the node at the end of the sample
+ sum(mst_end(m, s_, t_),
+ sum(sft(s_, f_, t_),
+ v_state(grid, node, s_, f_, t_)
// Initial value of the state of the node at the start of the sample s_
+ sum(mst_start(m, s_, t),
+ sum(sft(s_, f, t),
+ v_state(grid, node, s_, f+df(f,t+dt(t)), t+dt(t))
) // END sum(ft)
) // END sum(mst_end)
) // END sum(mst_start)
// Change in the state value over the sample s_, multiplied by sample s_ temporal weight
+ p_msWeight(m, s_)
* [
// State of the node at the end of the sample s_
+ sum(mst_end(m, s_, t),
+ sum(sft(s_, f, t),
+ v_state(grid, node, s_, f, t)
) // END sum(ft)
) // END sum(mst_end)
// State of the node at the end of the sample s_
- sum(mst_start(m, s_, t),
+ sum(sft(s_, f, t),
+ v_state(grid, node, s_, f+df(f,t+dt(t)), t+dt(t))
) // END sum(ft)
) // END sum(mst_start)
] // END * p_msWeight(m, s_)
;
*--- Minimum Inertia ----------------------------------------------------------
......
......@@ -286,6 +286,7 @@ $ifthen defined scenario
// Select root sample and central forecast
loop((ms_initial(mSolve, s_), mf_central(mSolve, f)),
s_active(s_) = yes;
p_msProbability(mSolve, s_)$mSettings(mSolve, 'scenarios') = 1;
loop(scenario$(ord(scenario) <= mSettings(mSolve, 'scenarios')),
s_scenario(s_, scenario) = yes;
if(mSettings(mSolve, 'scenarios') > 1,
......@@ -356,11 +357,6 @@ loop(s_scenario(s, scenario)$(ord(s) > 1 and ord(scenario) > 1),
= (ord(scenario) - 1) * mSettings(mSolve, 'scenarioLength');
);
loop(gn_scenarios(grid, node, param_gnBoundaryTypes),
dt_scenarioOffset(grid, node, param_gnBoundaryTypes, s)
= (ord(scenario) - 1) * mSettings(mSolve, 'scenarioLength');
);
loop(gn_scenarios(flow, node, timeseries),
dt_scenarioOffset(flow, node, timeseries, s)
= (ord(scenario) - 1) * mSettings(mSolve, 'scenarioLength');
......@@ -450,13 +446,27 @@ df(f_solve(f), t_active(t))${ ord(t) <= tSolveFirst + max(mSettings(mSolve, 't_j
min(mSettings(mSolve, 't_perfectForesight'),
currentForecastLength))}
= sum(mf_realization(mSolve, f_), ord(f_) - ord(f));
// Displacement to reach the realized forecast
Option clear = df_realization;
loop(mf_realization(mSolve, f_),
df_realization(ft(f, t))$[ord(t) <= tSolveFirst + currentForecastLength]
= ord(f_) - ord(f);
);
// Central forecast for the long-term scenarios comes from a special forecast label
Option clear = df_scenario;
if(mSettings(mSolve, 'scenarios') > 1,
loop((ms_initial(mSolve, s), mf_central(mSolve, f)),
df_scenario(f_solve(f), t_active(t))${ord(t) > msEnd(mSolve, s)}
= sum(mf_scenario(mSolve, f_), ord(f_) - ord(f));
loop((msft(ms_central(mSolve, s), f, t), mf_scenario(mSolve, f_)),
df_scenario(ft(f, t)) = ord(f_) - ord(f);
);
);
// Check that df_forecast and df_scenario do not overlap
loop(ft(f, t),
if(df_realization(f, t) <> 0 and df_scenario(f, t) <> 0,
put log "!!! Overlapping period of using realization and scenarios"/;
put log "!!! Check forecast lengths, `gn_scenarios` and `gn_forecasts`"/;
execError = execError + 1;
);
);
// Forecast displacement between central and forecasted intervals at the end of forecast horizon
Option clear = df_central; // This can be reset.
......
......@@ -322,17 +322,19 @@ $offtext
ts_influx_(gn(grid, node), fts(f, tt_interval(t), s))
= sum(tt_aggregate(t, t_),
ts_influx(grid, node,
f + (df_scenario(f, t)$gn_scenarios(grid, node, 'ts_influx')),
t_+ ( + dt_scenarioOffset(grid, node, 'ts_influx', s)
+ dt_circular(t_)$(not gn_scenarios(grid, node, 'ts_influx'))))
f + ( df_realization(f, t)$(not gn_forecasts(grid, node, 'ts_influx'))
+ df_scenario(f, t)$gn_scenarios(grid, node, 'ts_influx')),
t_+ (+ dt_scenarioOffset(grid, node, 'ts_influx', s)
+ dt_circular(t_)$(not gn_scenarios(grid, node, 'ts_influx'))))
)
/ mInterval(mSolve, 'stepsPerInterval', counter);
ts_cf_(flowNode(flow, node), fts(f, tt_interval(t), s))
= sum(tt_aggregate(t, t_),
ts_cf(flow, node,
f + (df_scenario(f, t)$gn_scenarios(flow, node, 'ts_cf')),
t_+ ( + dt_scenarioOffset(flow, node, 'ts_cf', s)
+ dt_circular(t_)$(not gn_scenarios(flow, node, 'ts_cf'))))
f + ( df_realization(f, t)$(not gn_forecasts(flow, node, 'ts_cf'))
+ df_scenario(f, t)$gn_scenarios(flow, node, 'ts_cf')),
t_+ ( dt_scenarioOffset(flow, node, 'ts_cf', s)
+ dt_circular(t_)$(not gn_scenarios(flow, node, 'ts_cf'))))
)
/ mInterval(mSolve, 'stepsPerInterval', counter);
// Reserves relevant only until reserve_length
......@@ -340,7 +342,8 @@ $offtext
${ord(t) <= tSolveFirst + p_nReserves(node, restype, 'reserve_length') }
= sum(tt_aggregate(t, t_),
ts_reserveDemand(restype, up_down, node,
f + (df_scenario(f, t)$gn_scenarios(restype, node, 'ts_reserveDemand')),
f + ( df_realization(f, t)$(not gn_forecasts(restype, node, 'ts_reserveDemand'))
+ df_scenario(f, t)$gn_scenarios(restype, node, 'ts_reserveDemand')),
t_+ dt_circular(t_))
)
/ mInterval(mSolve, 'stepsPerInterval', counter);
......@@ -349,7 +352,8 @@ $offtext
// Take average if not a limit type
= (sum(tt_aggregate(t, t_),
ts_node(grid, node, param_gnBoundaryTypes,
f + (df_scenario(f, t)$gn_scenarios(grid, node, 'ts_node')),
f + ( df_realization(f, t)$(not gn_forecasts(grid, node, 'ts_node'))
+ df_scenario(f, t)$gn_scenarios(grid, node, 'ts_node')),
t_+ ( + dt_scenarioOffset(grid, node, param_gnBoundaryTypes, s)
+ dt_circular(t_)$(not gn_scenarios(grid, node, 'ts_node'))))
)
......@@ -359,7 +363,8 @@ $offtext
// Maximum lower limit
+ smax(tt_aggregate(t, t_),
ts_node(grid, node, param_gnBoundaryTypes,
f + (df_scenario(f, t)$gn_scenarios(grid, node, 'ts_node')),
f + ( df_realization(f, t)$(not gn_forecasts(grid, node, 'ts_node'))
+ df_scenario(f, t)$gn_scenarios(grid, node, 'ts_node')),
t_+ ( + dt_scenarioOffset(grid, node, param_gnBoundaryTypes, s)
+ dt_circular(t_)$(not gn_scenarios(grid, node, 'ts_node'))))
)
......@@ -367,7 +372,8 @@ $offtext
// Minimum upper limit
+ smin(tt_aggregate(t, t_),
ts_node(grid, node, param_gnBoundaryTypes,
f + (df_scenario(f, t)$gn_scenarios(grid, node, 'ts_node')),
f + ( df_realization(f, t)$(not gn_forecasts(grid, node, 'ts_node'))
+ df_scenario(f, t)$gn_scenarios(grid, node, 'ts_node')),
t_+ ( + dt_scenarioOffset(grid, node, param_gnBoundaryTypes, s)
+ dt_circular(t_)$(not gn_scenarios(grid, node, 'ts_node'))))
)
......@@ -422,7 +428,8 @@ Option clear = p_msft_probability;
p_msft_probability(msft(mSolve, s, f, t))
= p_mfProbability(mSolve, f)
/ sum(f_${ft(f_, t)},
p_mfProbability(mSolve, f_)) * p_msProbability(mSolve, s);
p_mfProbability(mSolve, f_)) * p_msProbability(mSolve, s)
* p_msWeight(mSolve, s);
* --- Calculate sample displacements ------------------------------------------
......@@ -445,6 +452,9 @@ This avoids a discontinuity `jump' after the initial sample.
Transm. Distrib., vol. 12, no. 2, pp. 441 - 447, 2018.
$offtext
* Check that we have values for the autocorrelations
$ifthen.autocorr defined p_autocorrelation
// Do smoothing
if(mSettings(mSolve, 'scenarios'), // Only do smooting if using long-term scenarios
// Select the initial sample, first `t` not in it and `f` of the last `t` in it
......@@ -454,4 +464,5 @@ if(mSettings(mSolve, 'scenarios'), // Only do smooting if using long-term scena
$$batinclude 'inc/smoothing.gms' ts_influx
$$batinclude 'inc/smoothing.gms' ts_cf
);
); // END if('scenarios')
\ No newline at end of file
); // END if('scenarios')
$endif.autocorr
......@@ -96,35 +96,35 @@ loop(m,
r_gnuTotalVOMCost(gnu_output(grid, node, unit))
= sum(ft_realizedNoReset(f,t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
+ r_gnuVOMCost(grid, node, unit, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s))
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
);
// Total fuel & emission costs
r_uTotalFuelEmissionCost(fuel, unit)${ uFuel(unit, 'main', fuel) }
= sum(ft_realizedNoReset(f,t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
+ r_uFuelEmissionCost(fuel, unit, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s))
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
);
// Total unit startup costs
r_uTotalStartupCost(unit)${ sum(starttype, unitStarttype(unit, starttype)) }
= sum(ft_realizedNoReset(f,t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
+ r_uStartupCost(unit, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s))
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
);
// Total state variable slack costs
r_gnTotalStateSlackCost(gn_stateSlack(grid, node))
= sum(ft_realizedNoReset(f,t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
+ r_gnStateSlackCost(grid, node, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s))
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
);
// Fixed O&M costs
r_gnuFOMCost(gnu(grid, node, unit))
= 1e-6 // Scaling to MEUR
* [
+ p_gnu(grid, node, unit, 'maxGen') // Not in v_obj
+ p_gnu(grid, node, unit, 'maxGen') // Not in v_obj
+ p_gnu(grid, node, unit, 'maxCons') // Not in v_obj
+ r_invest(unit)
* p_gnu(grid, node, unit, 'unitSizeTot')
......@@ -196,7 +196,7 @@ loop(m,
= sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
+ r_gen(grid, node, unit, f, t)
* p_stepLengthNoReset(m, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s))
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
); // END sum(ft_realizedNoReset)
// Energy generation by fuels
......@@ -219,7 +219,7 @@ loop(m,
= sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
+ r_genFuel(grid, node, fuel, f, t)
* p_stepLengthNoReset(m, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s))
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
); // END sum(ft_realizedNoReset)
// Total dummy generation/consumption
......@@ -227,7 +227,7 @@ loop(m,
= sum(ft_realizedNoReset(f,t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
+ r_qGen(inc_dec, grid, node, f, t)
* p_stepLengthNoReset(m, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s))
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
); // END sum(ft_realizedNoReset)
* --- Total Unit Online Results -----------------------------------------------
......@@ -237,7 +237,7 @@ loop(m,
= sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
+ r_online(unit, f, t)
* p_stepLengthNoReset(m, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s))
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
); // END sum(ft_realizedNoReset)
// Approximate utilization rates for gnus over the simulation
......@@ -256,7 +256,7 @@ loop(m,
= sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
+ r_reserve(restype, up_down, node, unit, f, t)
* p_stepLengthNoReset(m, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s))
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
); // END sum(ft_realizedNoReset)
// Total dummy reserve provisions over the simulation
......@@ -264,7 +264,7 @@ loop(m,
= sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
+ r_qResDemand(restype, up_down, node, f, t)
* p_stepLengthNoReset(m, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s))
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
); // END sum(ft_realizedNoReset)
* --- Total Transfer and Spill ------------------------------------------------
......@@ -274,7 +274,7 @@ loop(m,
= sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
+ r_transfer(grid, from_node, to_node, f, t)
* p_stepLengthNoReset(m, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s))
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
); // END sum(ft_realizedNoReset)
// Total energy spill from nodes
......@@ -282,7 +282,7 @@ loop(m,
= sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
+ r_spill(grid, node, f, t)
* p_stepLengthNoReset(m, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s))
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
); // END sum(ft_realizedNoReset)
* =============================================================================
......@@ -331,7 +331,7 @@ r_gTotalqGen(inc_dec, grid)
r_gnTotalConsumption(gn(grid, node))
= sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
+ r_gnConsumption(grid, node, f ,t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s))
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
);
// Total consumption in each grid over the simulation
......@@ -375,7 +375,7 @@ r_gnTotalSpillShare(gn(grid, node_spill))${ r_gTotalSpill(grid) > 0 }
r_gnTotalRealizedOperatingCost(gn(grid, node))
= sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
+ r_gnRealizedOperatingCost(grid, node, f ,t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s))
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
);
// Total realized net operating costs on each gn over the simulation
......@@ -473,14 +473,14 @@ r_uTotalOnlinePerUnit(unit)${ p_unit(unit, 'unitCount') > 0 }
r_uTotalStartup(unit, starttype)
= sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
+ r_startup(unit, starttype, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s))
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
); // END sum(ft_realizedNoReset)
// Total sub-unit shutdowns over the simulation
r_uTotalShutdown(unit)
= sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
+ r_shutdown(unit, f, t)
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s))
* sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
); // END sum(ft_realizedNoReset)
* --- Diagnostic Results ------------------------------------------------------
......
......@@ -31,7 +31,7 @@ set metadata(*) /
'GAMS system' '%system.gstring%'
$include 'version'
/;
if(errorcount > 0, metadata('FAILED') = yes);
if(execError > 0, metadata('FAILED') = yes);
put f_info
put ""/;
......
......@@ -18,6 +18,9 @@ $offtext
* Argument gives time series type
$setargs timeseries
* Check that we have values for the standard deviation
$ifthen.std defined %timeseries%_std
* Select set linking nodes based on the time series type
$ifthen %timeseries% == 'ts_cf'
$setlocal linking_set flowNode
......@@ -31,7 +34,10 @@ $endif
= min(p_tsMaxValue(%linking_set%, '%timeseries%'),
max(p_tsMinValue(%linking_set%, '%timeseries%'),
%timeseries%_(%linking_set%, f, t, s)
+ (%timeseries%(%linking_set%, f_, t_)
+ (%timeseries%(%linking_set%,
f_ + (df_realization(f_, t_)
$(not gn_forecasts(%linking_set%, '%timeseries%'))),
t_)
- %timeseries%(%linking_set%,
f + (df_scenario(f, t)$gn_scenarios(%linking_set%,
'%timeseries%')),
......@@ -46,3 +52,4 @@ $endif
* power(p_autocorrelation(%linking_set%, '%timeseries%'),
abs(ord(t) - ord(t_)))
));
$endif.std
Markdown is supported
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