4b_outputInvariant.gms 31.4 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ontext
This file is part of Backbone.

Backbone is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Backbone is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with Backbone.  If not, see <http://www.gnu.org/licenses/>.
$offtext

18
* =============================================================================
19
* --- Time Step Dependent Results ---------------------------------------------
20
* =============================================================================
21

22
23
// Need to loop over the model dimension, as this file is no longer contained in the modelSolves loop...
loop(m,
24

Topi Rasku's avatar
Topi Rasku committed
25
26
27
* --- Realized Individual Costs ----------------------------------------------

    // Variable O&M costs
28
    r_gnuVOMCost(gnu(grid, node, unit), ft_realizedNoReset(f,t))$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')]
Topi Rasku's avatar
Topi Rasku committed
29
30
        = 1e-6 // Scaling to MEUR
            * p_stepLengthNoReset(m, f, t)
31
            * abs(r_gen(grid, node, unit, f, t))
32
            * p_gnu(grid, node, unit, 'vomCosts');
Topi Rasku's avatar
Topi Rasku committed
33
34

    // Fuel and emission costs during normal operation
35
    r_uFuelEmissionCost(commodity, unit_commodity(unit), ft_realizedNoReset(f,t))${ un_commodity(unit, commodity) and [ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')]}
Topi Rasku's avatar
Topi Rasku committed
36
37
        = 1e-6 // Scaling to MEUR
            * p_stepLengthNoReset(m, f, t)
38
            * r_fuelUse(commodity, unit, f, t)
39
40
            * [ + p_price(commodity, 'price')$p_price(commodity, 'useConstant')
                + ts_price(commodity, t)$p_price(commodity, 'useTimeSeries')
Topi Rasku's avatar
Topi Rasku committed
41
                // Emission costs
42
43
                + sum(emission, p_unitEmissionCost(unit, commodity, emission))
              ];
Topi Rasku's avatar
Topi Rasku committed
44
45

    // Unit startup costs
46
    r_uStartupCost(unit, ft_realizedNoReset(f,t))${sum(starttype, unitStarttype(unit, starttype)) and [ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')]}
Topi Rasku's avatar
Topi Rasku committed
47
48
49
        = 1e-6 // Scaling to MEUR
            * sum(unitStarttype(unit, starttype),
                + r_startup(unit, starttype, f, t)
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
                    * [
                        + p_uStartup(unit, starttype, 'cost') // CUR/start-up
                        // Start-up fuel and emission costs
                        + sum(nu(node,unit)$p_unStartup(unit, node, starttype),
                            + p_unStartup(unit, node, starttype) // MWh/start-up
                              * [
                                  + p_price(node, 'price')$p_price(node, 'useConstant') // CUR/MWh
                                  + ts_price(node, t)$p_price(node, 'useTimeseries') // CUR/MWh
                                ] // END * p_uStartup
                          ) // END sum(node)
                        + sum((nu(node, unit), emission)$p_unitEmissionCost(unit, node, emission),
                            + p_unStartup(unit, node, starttype) // MWh/start-up
                              * p_unitEmissionCost(unit, node, emission) // CUR/MWh
                          ) // END sum(nu, emission)
                      ] // END * r_startup
65
              ); // END sum(starttype)
Topi Rasku's avatar
Topi Rasku committed
66

67
68
    //Variable Trnasfer Costs
    r_gnnVariableTransCost(gn2n_directional(grid, node_, node), ft_realizedNoReset(f,t))$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')]
69
70
        = 1e-6 // Scaling to MEUR
            * p_stepLengthNoReset(m, f, t)
71
                    *[+ p_gnn(grid, node, node_, 'variableTransCost')
72
                    * r_transferLeftward(grid, node_, node, f, t)
73
                    + p_gnn(grid, node_, node, 'variableTransCost')
74
75
                    * r_transferRightward(grid, node_, node, f, t)];

Topi Rasku's avatar
Topi Rasku committed
76
    // Node state slack costs
77
    r_gnStateSlackCost(gn_stateSlack(grid, node), ft_realizedNoReset(f,t))$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')]
Topi Rasku's avatar
Topi Rasku committed
78
79
80
81
82
83
84
85
        = 1e-6 // Scaling to MEUR
            * p_stepLengthNoReset(m, f, t)
            * sum(slack${ p_gnBoundaryPropertiesForStates(grid, node, slack, 'slackCost') },
                + r_stateSlack(grid, node, slack, f, t)
                    * p_gnBoundaryPropertiesForStates(grid, node, slack, 'slackCost')
                ); // END sum(slack)

    // Storage Value Change
86
    r_gnStorageValueChange(gn_state(grid, node))${ active(m, 'storageValue') }
Topi Rasku's avatar
Topi Rasku committed
87
88
89
        = 1e-6
            * [
                + sum(ft_realizedNoReset(f,t)${ ord(t) = mSettings(m, 't_end') + 1 },
90
                    + [
Topi Rasku's avatar
Topi Rasku committed
91
                        + p_storageValue(grid, node)${ not p_gn(grid, node, 'storageValueUseTimeSeries') }
92
93
                        + ts_storageValue(grid, node, f, t)${ p_gn(grid, node, 'storageValueUseTimeSeries') }
                      ]
Topi Rasku's avatar
Topi Rasku committed
94
95
                        * r_state(grid, node, f, t)
                    ) // END sum(ft_realizedNoReset)
96
                - sum(ft_realizedNoReset(f,t)${ ord(t) = mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod') }, // INITIAL v_state NOW INCLUDED IN THE RESULTS
97
                    + [
Topi Rasku's avatar
Topi Rasku committed
98
                        + p_storageValue(grid, node)${ not p_gn(grid, node, 'storageValueUseTimeSeries') }
99
100
                        + ts_storageValue(grid, node, f, t)${ p_gn(grid, node, 'storageValueUseTimeSeries') }
                      ]
Topi Rasku's avatar
Topi Rasku committed
101
102
103
104
                        * r_state(grid, node, f, t)
                    ) // END sum(ft_realizedNoReset)
                ]; // END * 1e-6

105
* --- Total Cost Components (discounted) --------------------------------------
Topi Rasku's avatar
Topi Rasku committed
106
107
108

    // Total VOM costs
    r_gnuTotalVOMCost(gnu_output(grid, node, unit))
109
        = sum(ft_realizedNoReset(f,t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
Topi Rasku's avatar
Topi Rasku committed
110
            + r_gnuVOMCost(grid, node, unit, f, t)
111
                * sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s) * p_s_discountFactor(s))
Topi Rasku's avatar
Topi Rasku committed
112
113
            );

114
115
    // Total Variable Transfer costs
    r_gnnTotalVariableTransCost(gn2n_directional(grid, node_, node))
116
        = sum(ft_realizedNoReset(f,t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
117
            + r_gnnVariableTransCost(grid, node_, node, f, t)
118
119
120
                * sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s) * p_s_discountFactor(s))
            );

Topi Rasku's avatar
Topi Rasku committed
121
    // Total fuel & emission costs
122
    r_uTotalFuelEmissionCost(commodity, unit)$un_commodity(unit, commodity)
123
        = sum(ft_realizedNoReset(f,t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
124
            + r_uFuelEmissionCost(commodity, unit, f, t)
125
                * sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s) * p_s_discountFactor(s))
Topi Rasku's avatar
Topi Rasku committed
126
127
128
129
            );

    // Total unit startup costs
    r_uTotalStartupCost(unit)${ sum(starttype, unitStarttype(unit, starttype)) }
130
        = sum(ft_realizedNoReset(f,t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
Topi Rasku's avatar
Topi Rasku committed
131
            + r_uStartupCost(unit, f, t)
132
                * sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s) * p_s_discountFactor(s))
Topi Rasku's avatar
Topi Rasku committed
133
134
135
136
            );

    // Total state variable slack costs
    r_gnTotalStateSlackCost(gn_stateSlack(grid, node))
137
        = sum(ft_realizedNoReset(f,t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
Topi Rasku's avatar
Topi Rasku committed
138
            + r_gnStateSlackCost(grid, node, f, t)
139
                * sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s) * p_s_discountFactor(s))
Topi Rasku's avatar
Topi Rasku committed
140
141
            );

Niina Helistö's avatar
Niina Helistö committed
142
143
144
    // Fixed O&M costs
    r_gnuFOMCost(gnu(grid, node, unit))
        = 1e-6 // Scaling to MEUR
145
146
            * sum(ms(m, s)${ sum(msft_realizedNoReset(m, s, f, t_), 1) }, // consider ms only if it has active msft_realizedNoReset
                + [
147
                    + p_gnu(grid, node, unit, 'capacity')$sum(msft_realizedNoReset(m, s, f, t_), uft(unit, f, t_)) // Not in v_obj; only units active in msft_realizedNoReset
148
                    + r_invest(unit)$sum(msft_realizedNoReset(m, s, f, t_), uft(unit, f, t_)) // only units active in msft_realizedNoReset
149
                        * p_gnu(grid, node, unit, 'unitSize')
150
151
                    ]
                    * p_msAnnuityWeight(m, s) // Sample weighting to calculate annual costs
152
                    * p_s_discountFactor(s) // Discount costs
153
                ) // END * sum(ms)
Niina Helistö's avatar
Niina Helistö committed
154
155
156
157
158
            * p_gnu(grid, node, unit, 'fomCosts');

    // Unit investment costs
    r_gnuUnitInvestmentCost(gnu(grid, node, unit))
        = 1e-6 // Scaling to MEUR
159
            * sum(ms(m, s)${ sum(msft_realizedNoReset(m, s, f, t_), 1) }, // consider ms only if it has active msft_realizedNoReset
160
                + r_invest(unit)$sum(msft_realizedNoReset(m, s, f, t_), uft(unit, f, t_)) // only units active in msft_realizedNoReset
161
                    * p_msAnnuityWeight(m, s) // Sample weighting to calculate annual costs
162
                    * p_s_discountFactor(s) // Discount costs
163
                ) // END * sum(ms)
164
            * p_gnu(grid, node, unit, 'unitSize')
Niina Helistö's avatar
Niina Helistö committed
165
166
167
168
            * p_gnu(grid, node, unit, 'invCosts')
            * p_gnu(grid, node, unit, 'annuity');

    // Transfer link investment costs
169
    r_gnnLinkInvestmentCost(gn2n_directional(grid, from_node, to_node)) // gn2n_directional only, as in q_obj
Niina Helistö's avatar
Niina Helistö committed
170
        = 1e-6 // Scaling to MEUR
171
172
173
174
175
            * sum(ms(m, s)${ sum(msft_realizedNoReset(m, s, f, t_), 1) }, // consider ms only if it has active msft_realizedNoReset
                + sum(t_invest(t)${ord(t) <= msEnd(m, s)}, // only if investment was made before or during the sample
                    + r_investTransfer(grid, from_node, to_node, t)
                    )
                    * p_msAnnuityWeight(m, s) // Sample weighting to calculate annual costs
176
                    * p_s_discountFactor(s) // Discount costs
177
                ) // END * sum(ms)
Niina Helistö's avatar
Niina Helistö committed
178
179
180
181
182
183
184
            * [
                + p_gnn(grid, from_node, to_node, 'invCost')
                    * p_gnn(grid, from_node, to_node, 'annuity')
                + p_gnn(grid, to_node, from_node, 'invCost')
                    * p_gnn(grid, to_node, from_node, 'annuity')
                ]; // END * r_investTransfer;

185
186
* --- Realized Nodal System Costs ---------------------------------------------

Niina Helistö's avatar
Niina Helistö committed
187
    // Total realized gn operating costs
188
    r_gnRealizedOperatingCost(gn(grid, node), ft_realizedNoReset(f, t))$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')]
189
190
191
192
193
194
        = + sum(gnu(grid, node, unit),
              // VOM costs
              + r_gnuVOMCost(grid, node, unit, f, t)
            )
          // Allocate fuel and startup costs on energy basis, but for output nodes only
          + sum(unit$gnu(grid, node, unit),
195
196
197
198
199
200
              + [
                  + abs{r_gen(grid, node, unit, f, t)}  // abs is due to potential negative outputs like energy from a cooling unit. It's the energy contribution that matters, not direction.
                      / sum(gnu_output(grid_output, node_output, unit),
                          + abs{r_gen(grid_output, node_output, unit, f, t)}
                        ) // END sum(gnu_output)
                ]$(gnu_output(grid, node, unit) and abs{r_gen(grid, node, unit, f, t)} > eps)
201
202
203
204
205
206
                *
                {
                  + sum(un_commodity(unit, commodity), r_uFuelEmissionCost(commodity, unit, f, t))
                  + r_uStartupCost(unit, f, t)
                }
            )
207
          + sum(gn2n_directional(grid, node_, node),
208
209
              // Variable Transfer costs
              + r_gnnVariableTransCost(grid, node_, node, f, t)
210
            )
211
212
          // Node state slack costs
          + r_gnStateSlackCost(grid, node, f, t);
213
214
215
216

* --- Realized Nodal Energy Consumption ---------------------------------------
// !!! NOTE !!! This is a bit of an approximation at the moment !!!!!!!!!!!!!!!

217
    r_gnConsumption(gn(grid, node), ft_realizedNoReset(f, t))$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')]
218
219
220
221
222
223
224
225
        = p_stepLengthNoReset(m, f, t)
            * [
                + min(ts_influx(grid, node, f, t), 0) // Not necessarily a good idea, as ts_influx contains energy gains as well...
                + sum(gnu_input(grid, node, unit),
                    + r_gen(grid, node, unit, f, t)
                    ) // END sum(gnu_input)
                ];

226
227
228
* --- Total Energy Generation -------------------------------------------------

    // Total energy generation
229
    r_gnuTotalGen(gnu_output(grid, node, unit))
230
        = sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
231
232
            + r_gen(grid, node, unit, f, t)
                * p_stepLengthNoReset(m, f, t)
233
                * sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
234
            ); // END sum(ft_realizedNoReset)
235

236
237
238
239
240
241
242
243
244
    r_gen_gnUnittype(gn(grid, node), unittype)$sum(unit$unitUnittype(unit, unittype), 1)
      = sum(gnu(grid,node,unit)$unitUnittype(unit, unittype),
            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) * p_msWeight(m, s))
            ) // END sum(ft_realizedNoReset)
        );

245
    // Energy generation by fuels
246
247
248
    r_genFuel(gn(grid, node), commodity, ft_realizedNoReset(f, t))$[    sum(gnu_input(grid_, node_, unit)$gnu_output(grid, node, unit), r_gen(grid_, node_, unit, f, t))
                                                                    and ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')]
        = sum(gnu_output(grid, node, unit)$sum(gnu_input(grid_, commodity, unit), 1),
249
            + r_gen(grid, node, unit, f, t)
250
251
252
253
254
255
256
257
258
          );
// The calculation with multiple inputs needs to be fixed below (right share for different commodities - now units with multiple input commodities will get the same amount allocated which will then be too big
//          * sum((grid_, unit)$gnu_output(grid, node, unit),
//                r_gen(grid_, commodity, unit, f, t))
//                  / sum(gnu_input(grid__, node_, unit), r_gen(grid__, node_, unit, f, t));

    r_genFuel(gn(grid, node), flow, ft_realizedNoReset(f, t))$flowNode(flow, node)
        = sum(gnu_output(grid, node, unit)$flowUnit(flow, unit),
            + r_gen(grid, node, unit, f, t));
259

Juha Kiviluoma's avatar
Juha Kiviluoma committed
260
    // Energy generation by fuels
261
262
263
264
    r_genUnittype(gn(grid, node), unittype, ft_realizedNoReset(f,t))
        ${  sum(unit,gnu_output(grid, node, unit))
            and [ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')]
            }
Juha Kiviluoma's avatar
Juha Kiviluoma committed
265
        = sum(unit${unitUnittype(unit, unittype) and gnu_output(grid, node, unit)},
266
            + r_gen(grid, node, unit, f, t)
Juha Kiviluoma's avatar
Juha Kiviluoma committed
267
268
            ); // END sum(unit)

269
    // Total generation on each node by fuels
270
    r_gnTotalGenFuel(gn(grid, node), commodity)
271
        = sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
272
            + r_genFuel(grid, node, commodity, f, t)
273
                * p_stepLengthNoReset(m, f, t)
274
                * sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
275
            ); // END sum(ft_realizedNoReset)
276

277
278
    // Total dummy generation/consumption
    r_gnTotalqGen(inc_dec, gn(grid, node))
279
        = sum(ft_realizedNoReset(f,t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
280
281
            + r_qGen(inc_dec, grid, node, f, t)
                * p_stepLengthNoReset(m, f, t)
282
                * sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
283
284
            ); // END sum(ft_realizedNoReset)

285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
* --- Emission Results --------------------------------------------------------

    // Emissions of units (only for commodities, not including startup fuels)
    r_emissions(commodity, emission, unit, ft_realizedNoReset(f,t))$ {un_commodity(unit, commodity) and [ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')]}
        =   + p_stepLengthNoReset(m, f, t)
            * r_fuelUse(commodity, unit, f, t)
            * p_nEmission(commodity, emission)
            / 1e3 // NOTE!!! Conversion to t/MWh from kg/MWh in data
    ;


    // Emission sums
    r_nuTotalEmissions (commodity, unit, emission)
        = sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
            + r_emissions(commodity, emission, unit, f, t)
                 * sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
            )
    ;

    r_nTotalEmissions(commodity, emission)
        = sum(unit, r_nuTotalEmissions (commodity, unit, emission))
    ;

    r_uTotalEmissions(unit, emission)
        = sum(commodity, r_nuTotalEmissions (commodity, unit, emission))
    ;

    r_totalEmissions (emission)
        = sum(commodity, r_nTotalEmissions(commodity, emission))
    ;

316
* --- Total Unit Online Results -----------------------------------------------
317

318
319
    // Total sub-unit-hours for units over the simulation
    r_uTotalOnline(unit)
320
        = sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
321
            + r_online(unit, f, t)
322
                * p_stepLengthNoReset(m, f, t)
323
                * sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
324
            ); // END sum(ft_realizedNoReset)
325

326
    // Approximate utilization rates for gnus over the simulation
327
    r_gnuUtilizationRate(gnu_output(grid, node, unit))${ r_gnuTotalGen(grid, node, unit)
328
                                                         and ( p_gnu(grid, node, unit, 'capacity')
329
                                                               or r_invest(unit)
330
331
                                                               )
                                                         }
332
333
        = r_gnuTotalGen(grid, node, unit)
            / [
334
                + (p_gnu(grid, node, unit, 'capacity') + r_invest(unit)*p_gnu(grid, node, unit, 'unitSize'))
335
                    * (mSettings(m, 't_end') - (mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')) + 1)
336
                    * mSettings(m, 'stepLengthInHours')
337
338
339
340
                ]; // END division

* --- Total Reserve Provision -------------------------------------------------

341
    // Total reserve provisions over the simulation
342
    r_gnuTotalReserve(gnuRescapable(restype, up_down, grid, node, unit))
343
        = sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
344
            + r_reserve(restype, up_down, grid, node, unit, f, t)
345
                * p_stepLengthNoReset(m, f, t)
346
                * sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
347
348
            ); // END sum(ft_realizedNoReset)

349
    // Total dummy reserve provisions over the simulation
350
    r_groupTotalqResDemand(restypeDirectionGroup(restype, up_down, group))
351
        = sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
352
            + r_qResDemand(restype, up_down, group, f, t)
353
                * p_stepLengthNoReset(m, f, t)
354
                * sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
355
356
            ); // END sum(ft_realizedNoReset)

357
358
359
360
* --- Total Transfer and Spill ------------------------------------------------

    // Total transfer of energy between nodes
    r_gnnTotalTransfer(gn2n(grid, from_node, to_node))
361
        = sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
362
            + r_transfer(grid, from_node, to_node, f, t)
363
                * p_stepLengthNoReset(m, f, t)
364
                * sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
365
366
            ); // END sum(ft_realizedNoReset)

367
368
    // Total energy spill from nodes
    r_gnTotalSpill(grid, node_spill(node))
369
        = sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
370
371
            + r_spill(grid, node, f, t)
                * p_stepLengthNoReset(m, f, t)
372
                * sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
373
            ); // END sum(ft_realizedNoReset)
374

375
376
377
378
* =============================================================================
* --- Futher Time Step Independent Results ------------------------------------
* =============================================================================

379
* --- Scaling Marginal Values to EUR/MWh from MEUR/MWh ------------------------
380
381

// Energy balance
382
r_balanceMarginal(gn(grid, node), ft_realizedNoReset(f, t))$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')]
383
384
385
    = 1e6 * r_balanceMarginal(grid, node, f, t);

// Reserve balance
386
387
r_resDemandMarginal(restypeDirectionGroup(restype, up_down, group), ft_realizedNoReset(f, t))$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')]
    = 1e6 * r_resDemandMarginal(restype, up_down, group, f, t);
388

389
390
* --- Total Generation Results ------------------------------------------------

391
392
// Total generation in gn
r_gnTotalGen(gn(grid, node))
393
394
    = sum(gnu_output(grid, node, unit), r_gnuTotalGen(grid, node, unit));

395
396
397
// Total generation in g
r_gTotalGen(grid)
    = sum(gn(grid, node), r_gnTotalGen(grid, node));
398

399
// Total generation gnu/gn shares
400
r_gnuTotalGenShare(gnu_output(grid, node, unit))${ r_gnTotalGen(grid, node) > 0 }
401
402
403
404
    = r_gnuTotalGen(grid, node, unit)
        / r_gnTotalGen(grid, node);

// Total generation gn/g shares
405
r_gnTotalGenShare(gn(grid, node))${ r_gTotalGen(grid) > 0 }
406
407
408
    = r_gnTotalGen(grid, node)
        / r_gTotalGen(grid);

409
410
411
412
413
414
* --- Total Dummy Generation Results ------------------------------------------

// Total dummy generaion in g
r_gTotalqGen(inc_dec, grid)
    = sum(gn(grid, node), r_gnTotalqGen(inc_dec, grid, node));

415
416
* --- Total Energy Consumption Results ----------------------------------------

417
418
// Total consumption on each gn over the simulation
r_gnTotalConsumption(gn(grid, node))
419
    = sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
Niina Helistö's avatar
Niina Helistö committed
420
        + r_gnConsumption(grid, node, f ,t)
421
            * sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
Niina Helistö's avatar
Niina Helistö committed
422
        );
423

424
425
426
// Total consumption in each grid over the simulation
r_gTotalConsumption(grid)
    = sum(gn(grid, node), r_gnTotalConsumption(grid, node));
427

428
// Total consumption gn/g share
429
r_gnTotalConsumptionShare(gn(grid, node))${ r_gTotalConsumption(grid) > 0 }
430
431
432
433
434
    = r_gnTotalConsumption(grid, node)
        / r_gTotalConsumption(grid);

* --- Total Fuel Consumption Results ------------------------------------------

435
// Total fuel consumption in grids over the simulation
436
437
r_gTotalGenFuel(grid, commodity)
    = sum(gn(grid, node), r_gnTotalGenFuel(grid, node, commodity));
438

439
// Total fuel consumption over the simulation
440
441
r_totalGenFuel(commodity)
    = sum(gn(grid, node), r_gnTotalGenFuel(grid, node, commodity));
442

443
// Total fuel consumption gn/g shares
444
445
r_gnTotalGenFuelShare(gn(grid, node), commodity)${ r_gnTotalGen(grid, node) }
    = r_gnTotalGenFuel(grid, node, commodity)
446
        / r_gnTotalGen(grid, node);
447
448
449

* --- Total Spilled Energy Results --------------------------------------------

450
451
452
// Total spilled energy in each grid over the simulation
r_gTotalSpill(grid)
    = sum(gn(grid, node_spill(node)), r_gnTotalSpill(grid, node));
453

454
// Total spilled energy gn/g share
455
r_gnTotalSpillShare(gn(grid, node_spill))${ r_gTotalSpill(grid) > 0 }
456
457
458
    = r_gnTotalSpill(grid, node_spill)
        / r_gTotalSpill(grid);

459
* --- Total Costs Results (discounted) ----------------------------------------
460

Niina Helistö's avatar
Niina Helistö committed
461
462
// Total realized operating costs on each gn over the simulation
r_gnTotalRealizedOperatingCost(gn(grid, node))
463
    = sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
Niina Helistö's avatar
Niina Helistö committed
464
        + r_gnRealizedOperatingCost(grid, node, f ,t)
465
            * sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s) * p_s_discountFactor(s))
Niina Helistö's avatar
Niina Helistö committed
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
        );

// Total realized net operating costs on each gn over the simulation
r_gnTotalRealizedNetOperatingCost(gn(grid, node))
    = r_gnTotalRealizedOperatingCost(grid, node) - r_gnStorageValueChange(grid, node);

// Total realized operating costs on each grid over the simulation
r_gTotalRealizedOperatingCost(grid)
    = sum(gn(grid, node), r_gnTotalRealizedOperatingCost(grid, node));

// Total realized net operating costs on each grid over the simulation
r_gTotalRealizedNetOperatingCost(grid)
    = sum(gn(grid, node), r_gnTotalRealizedNetOperatingCost(grid, node));

// Total realized operating costs gn/g share
481
r_gnTotalRealizedOperatingCostShare(gn(grid, node))${ r_gTotalRealizedOperatingCost(grid) > 0 }
Niina Helistö's avatar
Niina Helistö committed
482
483
484
485
486
487
488
489
490
491
492
    = r_gnTotalRealizedOperatingCost(grid, node)
        / r_gTotalRealizedOperatingCost(grid);

// Total realized operating costs over the simulation
r_totalRealizedOperatingCost
    = sum(gn(grid, node), r_gnTotalRealizedOperatingCost(grid, node));

// Total realized net operating costs over the simulation
r_totalRealizedNetOperatingCost
    = sum(gn(grid, node), r_gnTotalRealizedNetOperatingCost(grid, node));

493
494
// Total realized costs on each gn over the simulation
r_gnTotalRealizedCost(gn(grid, node))
Niina Helistö's avatar
Niina Helistö committed
495
496
497
498
499
500
501
    = r_gnTotalRealizedOperatingCost(grid, node)
        + sum(gnu(grid, node, unit),
            + r_gnuFOMCost(grid, node, unit)
            + r_gnuUnitInvestmentCost(grid, node, unit)
            )
        + sum(gn2n_directional(grid, from_node, node),
            + r_gnnLinkInvestmentCost(grid, from_node, node)
502
                / 2 // Half of the link costs are allocated to the receiving end
Niina Helistö's avatar
Niina Helistö committed
503
504
505
            )
        + sum(gn2n_directional(grid, node, to_node),
            + r_gnnLinkInvestmentCost(grid, node, to_node)
506
                / 2 // Half of the link costs are allocated to the sending end
Niina Helistö's avatar
Niina Helistö committed
507
            );
508

509
510
511
512
// Total realized net costs on each gn over the simulation
r_gnTotalRealizedNetCost(gn(grid, node))
    = r_gnTotalRealizedCost(grid, node) - r_gnStorageValueChange(grid, node);

513
514
515
// Total realized costs on each grid over the simulation
r_gTotalRealizedCost(grid)
    = sum(gn(grid, node), r_gnTotalRealizedCost(grid, node));
516

517
518
519
520
// Total realized net costs on each grid over the simulation
r_gTotalRealizedNetCost(grid)
    = sum(gn(grid, node), r_gnTotalRealizedNetCost(grid, node));

521
// Total realized costs gn/g share
522
r_gnTotalRealizedCostShare(gn(grid, node))${ r_gTotalRealizedCost(grid) > 0 }
523
524
525
    = r_gnTotalRealizedCost(grid, node)
        / r_gTotalRealizedCost(grid);

526
527
// Total realized costs over the simulation
r_totalRealizedCost
528
    = sum(gn(grid, node), r_gnTotalRealizedCost(grid, node));
529

Niina Helistö's avatar
Niina Helistö committed
530
// Total realized net operating costs over the simulation
531
532
533
r_totalRealizedNetCost
    = sum(gn(grid, node), r_gnTotalRealizedNetCost(grid, node));

534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
// Total realized fixed costs on each gn over the simulation
r_gnTotalRealizedFixedCost(gn(grid, node))
    = r_gnTotalRealizedCost(grid, node)
        - r_gnTotalRealizedOperatingCost(grid, node);

// Total realized fixed costs on each grid over the simulation
r_gTotalRealizedFixedCost(grid)
    = r_gTotalRealizedCost(grid)
        - r_gTotalRealizedOperatingCost(grid);

// Total realized fixed costs gn/g share
r_gnTotalRealizedFixedCostShare(gn(grid, node))${ r_gTotalRealizedFixedCost(grid) > 0 }
    = r_gnTotalRealizedFixedCost(grid, node)
        / r_gTotalRealizedFixedCost(grid);

// Total realized fixed costs over the simulation
r_totalRealizedFixedCost
    = r_totalRealizedCost
        - r_totalRealizedOperatingCost;

554
555
556
* --- Reserve Provision Overlap Results ---------------------------------------

// Calculate the overlapping reserve provisions
557
558
559
560
r_reserve2Reserve(gnuRescapable(restype, up_down, grid, node, unit), restype_, ft_realizedNoReset(f, t))
    ${ p_gnuRes2Res(grid, node, unit, restype, up_down, restype_) }
    = r_reserve(restype, up_down, grid, node, unit, f, t)
        * p_gnuRes2Res(grid, node, unit, restype, up_down, restype_);
561

562
563
* --- Total Reserve Provision Results -----------------------------------------

564
565
566
567
568
// Total reserve provision in groups over the simulation
r_groupTotalReserve(restypeDirectionGroup(restype, up_down, group))
    = sum(gnuRescapable(restype, up_down, grid, node, unit)${gnGroup(grid, node, group)},
        + r_gnuTotalReserve(restype, up_down, grid, node, unit)
    ); // END sum(gnuRescapable)
569

570
571
572
573
r_gnuTotalReserveShare(gnuRescapable(restype, up_down, grid, node, unit))
    ${ sum(gnGroup(grid, node, group), r_groupTotalReserve(restype, up_down, group)) > 0 }
    = r_gnuTotalReserve(restype, up_down, grid, node, unit)
        / sum(gnGroup(grid, node, group), r_groupTotalReserve(restype, up_down, group));
574
575
576

* --- Total Unit Online State Results -----------------------------------------

577
// Total unit online hours per sub-unit over the simulation
578
r_uTotalOnlinePerUnit(unit)${ p_unit(unit, 'unitCount') > 0 }
579
580
581
    = r_uTotalOnline(unit)
        / p_unit(unit, 'unitCount');

582
583
// Total sub-unit startups over the simulation
r_uTotalStartup(unit, starttype)
584
    = sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
585
        + r_startup(unit, starttype, f, t)
586
            * sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
587
588
589
590
        ); // END sum(ft_realizedNoReset)

// Total sub-unit shutdowns over the simulation
r_uTotalShutdown(unit)
591
    = sum(ft_realizedNoReset(f, t)$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')],
592
        + r_shutdown(unit, f, t)
593
            * sum(msft_realizedNoReset(m, s, f, t), p_msProbability(m, s) * p_msWeight(m, s))
594
595
        ); // END sum(ft_realizedNoReset)

596
597
598
599
600
601
602
603
* --- Sum results for groups --------------------------------------------------

// gnTotalgen in units that belong to gnuGroups over the simulation
r_gnTotalGenGnuGroup(grid, node, group)
    = sum(unit $ {gnuGroup(grid, node, unit, group)},
        + r_gnuTotalGen(grid, node, unit)
         ); // END sum(unit)

604
605
* --- Diagnostic Results ------------------------------------------------------

606
// Only include these if '--diag=yes' given as a command line argument
607
$iftheni.diag '%diag%' == yes
608
// Estimated coefficients of performance
609
610
611
d_cop(unit, ft_realizedNoReset(f, t))${  [ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')]
                                         and sum(gnu_input(grid, node, unit), 1)
                                         }
612
613
614
615
616
617
618
    = sum(gnu_output(grid, node, unit),
        + r_gen(grid, node, unit, f, t)
        ) // END sum(gnu_output)
        / [ sum(gnu_input(grid_, node_, unit),
                -r_gen(grid_, node_, unit, f, t)
                ) // END sum(gnu_input)
            + 1${not sum(gnu_input(grid_, node_, unit), -r_gen(grid_, node_, unit, f, t))}
619
620
            ]
        + Eps; // Eps to correct GAMS plotting (zeroes are not skipped)
621

622
// Estimated efficiency, calculated from commodity based inputs
623
d_eff(unit_commodity(unit), ft_realizedNoReset(f, t))$[ord(t) > mSettings(m, 't_start') + mSettings(m, 't_initializationPeriod')]
624
625
626
    = sum(gnu_output(grid, node, unit),
        + r_gen(grid, node, unit, f, t)
        ) // END sum(gnu_output)
627
628
629
630
        / [ sum(gnu_input(grid, node, unit)$un_commodity(unit, node),
                + r_fuelUse(node, unit, f, t)
                ) // END sum(gnu_input)
            + 1${not sum(gnu_input(grid, node, unit)$un_commodity(unit, node), r_fuelUse(node, unit, f, t))}
631
632
            ]
        + Eps; // Eps to correct GAMS plotting (zeroes are not skipped)
633
$endif.diag
634

635
); // END loop(m)
636