*_______________________________________________________________________________

*  This is a much-reduced version of the model DIETER.
*  It is used for the graphical illustrations in the review paper
*  "The Economics of Variable Renewables and Electricity Storage", written by
*  Javier Lopez Prol and Wolf-Peter Schill.
*  Previous versions of the model have been used for the papers
*  "Electricity storage and the renewable energy transition", https://doi.org/10.1016/j.joule.2020.07.022
*  and "On the economics of electrical storage for variable renewable energy sources", https://doi.org/10.1016/j.euroecorev.2018.07.004
*  Coded by Wolf-Peter Schill and Alexander Zerrahn
*  This work is licensed under the MIT License (MIT).
*  For more information on this license, visit http://opensource.org/licenses/mit-license.php.
*  Whenever you use this code, please refer to the Commentary and/or the
*  sources listed under http://www.diw.de/dieter.
*  We are happy to receive feedback under wschill@diw.de
*  October 15, 2020

*_______________________________________________________________________________


* Select RES share constraint or varying CO2 prices
$setglobal res_share_constr "*"
$setglobal varying_co2_prices ""


* ------------- Base year ------------------------------------------------------
* Select year between 2012 and 2018:
$setglobal base_year "2014"


* ------------- Sector Coupling ------------------------------------------------
* Select if additional flexible power-to-x demand should be considered by setting an asterisk (*) between ""
$setglobal sc ""

* Set SC electricity demand relative to conventional electricity demand (in %)
$setglobal sc_dem "8"

* Set SC capacity relative to conventional peak load (in %)
$setglobal sc_cap "50"

* Auxiliary string (do not change):
$if "%sc%" == "" $setglobal not_sc "*"
$if "%sc%" == "*" $setglobal not_sc ""
$if "%sc%" == "" $setglobal report_sc ""
$if "%sc%" == "*" $setglobal report_sc "_sc_dem%sc_dem%_sc_cap%sc_cap%"
* Sanity check (do not change):
$if not "%res_share_constr%%varying_co2_prices%" == "*" $abort 'Please select either RES share constraint or varying CO2 prices!'

Sets
h                Hours                                   /h1*h8760/
ct               Stylized dispatchable technologies      /coal,ccgt,ocgt/
*ct               Stylized dispatchable technologies      /coal/
res              Stylized renewable technologies         /wind, pv/
*sto              Stylized storage technologies           /liion_high,liion_low,phs,p2g2p_high,p2g2p_low/
sto              Stylized storage technologies           /phs/
sc               Stylized sector coupling technologies   /sc/


* Specify RES shares to any value between 0 and 100%
loop_res_share   Solution loop for different shares of renewables /0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100/
* Use the following to test the effects of different CO2 prices
*loop_res_share   Solution loop for different shares of renewables /0,20,40,60,80,100,120,140,160,180,200,300,400,500/

* Years for which data is provided in Excel file
year             Base years
/2012, 2013, 2014, 2015, 2016, 2017, 2018/

;

* for data upload
Sets
headers_con
headers_res
headers_sto
;

*-------------------------------------------------------------------------------

Variables
Z                        Objective
;

Positive variables
G_CON(ct,h)              Generation of conventional electricity
G_RENEWABLE(res,h)       Generation of renewable energy
CU(res,h)                Curtailment of renewable energy
N_RENEWABLE(res)         Capacities: renewable energy
N_CON(ct)                Capacities: conventional energy
N_STO_E(sto)             Capacities: storage energy
N_STO_P(sto)             Capacities: storage power
STO_L(sto,h)             Storage level
STO_IN(sto,h)            Storage loading
STO_OUT(sto,h)           Storage discharging
SC_IN(sc,h)              Sector coupling electricity consumption
INFES(h)                 Infeasibility variable
;

Parameters
eta_sto_in(sto)          Efficiency: storage in
eta_sto_out(sto)         Efficiency: storage out
phi_min_res              Minimum share of renewable electricity in net consumption
phi_max_curt             Maximum share of renewable electricity curtailed over the year
d(h)                     Electricity demand
d_upload(h,year)         Electricity demand - upload parameter
phi_res(res,h)           Hourly capacity factor renewable energy
phi_res_upload(h,res,year)       Hourly capacity factor renewable energy - upload parameter
c_i_sto_e(sto)           Cost: investment into storage energy
c_i_sto_p(sto)           Cost: investment into storage power
c_i_res(res)             Cost: investment into renewable capacity
c_i_con(ct)              Cost: investment into conventional capacity
c_var_con(ct)            Cost: variable generation costs conventional generators
c_var_sto(sto)           Cost: variable costs storage (both for charging and discharging)
sc_power(sc)             Sector coupling power rating
sc_flh(sc)               Sector coupling full-load hours
tech_con_upload(ct,headers_con)  Conventional technology data - upload parameter
tech_res_upload(res,headers_res) Renewable technology data - upload parameter
tech_sto_upload(sto,headers_sto) Storage technology data - upload parameter
;

*-------------------------------------------------------------------------------

* Upload time series data
$onecho >temp_time_series.tmp
par=d_upload             rng=time_series!a3:h8763        rdim=1 cdim=1
par=phi_res_upload       rng=time_series!j2:x8763        rdim=1 cdim=2
$offecho

$call "gdxxrw upload_data.xlsx @temp_time_series.tmp o=Data_input_time_series";
$GDXin Data_input_time_series.gdx
$load d_upload phi_res_upload
;

* Upload conventional technology data
$onecho >temp_tech_con.tmp
dset=headers_con         rng=tech_con!B5                 rdim=0 cdim=1
par=tech_con_upload      rng=tech_con!A5                 rdim=1 cdim=1
$offecho

$call "gdxxrw upload_data.xlsx @temp_tech_con.tmp o=Data_input_tech_con";
$GDXin Data_input_tech_con.gdx
$load headers_con tech_con_upload
;

* Upload renewable technology data
$onecho >temp_tech_res.tmp
dset=headers_res         rng=tech_res!B5                 rdim=0 cdim=1
par=tech_res_upload      rng=tech_res!A5                 rdim=1 cdim=1
$offecho

$call "gdxxrw upload_data.xlsx @temp_tech_res.tmp o=Data_input_tech_res";
$GDXin Data_input_tech_res.gdx
$load headers_res tech_res_upload
;

* Upload storage technology data
$onecho >temp_tech_sto.tmp
dset=headers_sto         rng=tech_sto!B5                 rdim=0 cdim=1
par=tech_sto_upload      rng=tech_sto!A5                 rdim=1 cdim=1
$offecho

$call "gdxxrw upload_data.xlsx @temp_tech_sto.tmp o=Data_input_tech_sto";
$GDXin Data_input_tech_sto.gdx
$load headers_sto tech_sto_upload
;

c_i_con(ct) = tech_con_upload(ct,'oc')*( tech_con_upload(ct,'interest_rate') * (1+tech_con_upload(ct,'interest_rate'))**(tech_con_upload(ct,'lifetime')) )
         / ( (1+tech_con_upload(ct,'interest_rate'))**(tech_con_upload(ct,'lifetime'))-1 )
         + tech_con_upload(ct,'fixed_costs') ;

c_i_res(res) = tech_res_upload(res,'oc')*( tech_res_upload(res,'interest_rate') * (1+tech_res_upload(res,'interest_rate'))**(tech_res_upload(res,'lifetime')) )
         / ( (1+tech_res_upload(res,'interest_rate'))**(tech_res_upload(res,'lifetime'))-1 )
         + tech_res_upload(res,'fixed_costs') ;

c_i_sto_e(sto) = tech_sto_upload(sto,'oc_energy')*( tech_sto_upload(sto,'interest_rate') * (1+tech_sto_upload(sto,'interest_rate'))**(tech_sto_upload(sto,'lifetime')) )
         / ( (1+tech_sto_upload(sto,'interest_rate'))**(tech_sto_upload(sto,'lifetime'))-1 ) ;

c_i_sto_p(sto) = tech_sto_upload(sto,'oc_power')*( tech_sto_upload(sto,'interest_rate') * (1+tech_sto_upload(sto,'interest_rate'))**(tech_sto_upload(sto,'lifetime')) )
         / ( (1+tech_sto_upload(sto,'interest_rate'))**(tech_sto_upload(sto,'lifetime'))-1 ) ;

c_var_con(ct) = tech_con_upload(ct,'fuel_costs')/tech_con_upload(ct,'eta_con')
         + tech_con_upload(ct,'carbon_content')/tech_con_upload(ct,'eta_con')*tech_con_upload(ct,'CO2_price') ;

c_var_sto(sto) = tech_sto_upload(sto,'vc') ;

eta_sto_in(sto) = sqrt(tech_sto_upload(sto,'eta_roundtrip')) ;
eta_sto_out(sto) = sqrt(tech_sto_upload(sto,'eta_roundtrip')) ;


* Initialize base year
phi_res(res,h) = phi_res_upload(h,res,'%base_year%') ;
d(h) = d_upload(h,'%base_year%') ;

* The following can be used to simulate a winter week without any renewable feed-in
$ontext
loop(h,
         phi_res(res,h)$(ord(h) > 168 and ord(h) <= 336) = 0 ;
) ;
display phi_res ;
$offtext


*_______________________________________________________________________________


Equations
objective                Objective function
energy_balance           Energy balance (market clearing)
renewable_generation     Use of renewable energy generation
renewable_share          Constraint on renewables share
fix_wind_pv_ratio        Constraint to fix wind and PV ratio (for easier comparison of RLDCs)

maximum_generation_con   Capacity constraint - conventional generation
stolev_start_end         Storage: storage level in the first and last period
stolev                   Storage: storage level dynamics
stolev_max               Storage: capacity constraint on maximum energy
maxin_power              Storage: capacity constraint on maximum power - storing in
maxout_power             Storage: capacity constraint on maximum power - storing out

maxin_sc                 Sector coupling: constraint on maximum power - electricity consumption
flh_sc                   Sector coupling: full-load hours
;

*-------------------------------------------------------------------------------
** OBJECTIVE FUNCTION

objective..
         Z =E= sum( ct , c_i_con(ct) * N_CON(ct) )
         + sum( res , c_i_res(res) * N_RENEWABLE(res) )
         + sum( sto , c_i_sto_e(sto) * N_STO_E(sto) + c_i_sto_p(sto) * N_STO_P(sto) )
         + sum( (ct,h) , c_var_con(ct) * G_CON(ct,h) )
         + sum( (sto,h) , c_var_sto(sto) * (STO_IN(sto,h) + STO_OUT(sto,h)) )
*         + sum( h , INFES(h) * 1000000)
;

*-------------------------------------------------------------------------------
** ENERGY BALANCE AND RENEWABLES USE

energy_balance(h)..
         sum( ct , G_CON(ct,h)) + sum( res , G_RENEWABLE(res,h)) + sum( sto , STO_OUT(sto,h))
*         + INFES(h)
         =E= d(h) + sum( sto , STO_IN(sto,h) )
%not_sc%         + sum( sc , SC_IN(sc,h))
;


renewable_generation(res,h)..
         phi_res(res,h) * N_RENEWABLE(res) =E= G_RENEWABLE(res,h) + CU(res,h)
;
$ontext
$offtext

*-------------------------------------------------------------------------------
** MINIMUM RENEWABLE SHARE

renewable_share..
* Note: VRE share is slightly over-constrained here (covers full storage losses), to prevent unintended storage cycling
%varying_co2_prices%%sc%             sum( (res,h) , G_RENEWABLE(res,h) ) =E= phi_min_res * sum( h , d(h) ) + sum( (sto,h) , STO_IN(sto,h) - STO_OUT(sto,h) )
%varying_co2_prices%%not_sc%         sum( (res,h) , G_RENEWABLE(res,h) ) =E= phi_min_res * sum( h , d(h) + sum( sc , SC_IN(sc,h) ) ) + sum( (sto,h) , STO_IN(sto,h) - STO_OUT(sto,h) )
%varying_co2_prices%$ontext
                 sum( (res,h) , G_RENEWABLE(res,h) ) =G= 0
$ontext
$offtext
;


*-------------------------------------------------------------------------------
** FIX WIND / PV RATIO (50/50 assumption for of simplicity)

fix_wind_pv_ratio..
         N_RENEWABLE('wind') =E= 0.5 * sum( res, N_RENEWABLE(res) )
;

*-------------------------------------------------------------------------------
** CONVENTIONAL GENERATION

maximum_generation_con(ct,h)..
         G_CON(ct,h) =L= N_CON(ct)
;

*-------------------------------------------------------------------------------
** STORAGE

stolev(sto,h)$( ord(h) > 1 )..
         STO_L(sto,h) =E= STO_L(sto,h-1) + STO_IN(sto,h) * eta_sto_in(sto) - STO_OUT(sto,h)/eta_sto_out(sto)
;

stolev_start_end(sto)..
         STO_L(sto,'h1') =E= STO_L(sto,'h8760')
;

stolev_max(sto,h)..
        STO_L(sto,h) =L= N_STO_E(sto)
;

maxin_power(sto,h)..
         STO_IN(sto,h) =L= N_STO_P(sto)
;

maxout_power(sto,h)..
         STO_OUT(sto,h) =L= N_STO_P(sto)
;


*-------------------------------------------------------------------------------
** SECTOR COUPLING

maxin_sc(sc,h)..
         SC_IN(sc,h) =L= sc_power(sc)
;

flh_sc(sc)..
         sum( h , SC_IN(sc,h)) =E= sc_flh(sc) * sc_power(sc)
;

*_______________________________________________________________________________


Model DIETER_reduced /
objective

energy_balance
renewable_generation
renewable_share
*fix_wind_pv_ratio
maximum_generation_con

stolev_start_end
stolev
stolev_max
maxin_power
maxout_power

%not_sc%maxin_sc
%not_sc%flh_sc
/


*_______________________________________________________________________________


options
optcr = 0.00
reslim = 10000000
lp = cplex
mip = cplex
nlp = conopt
dispwidth = 15
limrow = 0
limcol = 0
solprint = off
sysout = off
optcr = 1e-3
optca = 10
;

$onecho > cplex.opt
lpmethod 4
threads 4
epgap 1e-3
epagap 10
parallelmode -1
$offecho


DIETER_reduced.OptFile = 1;
DIETER_reduced.holdFixed = 1 ;

phi_min_res = eps ;
sc_power(sc) = eps ;
sc_flh(sc) = eps ;

* Reporting

* Parameters for the report file
Parameter
report
report_tech
report_hours
;


* Assign sc parameters
sc_power(sc) = %sc_cap%/100 * smax( h , d(h) ) ;
sc_flh(sc) = %sc_dem%/100 * sum( h , d(h) ) / sc_power(sc) ;


* Switch off storage manually
*N_STO_E.fx(sto) = 0 ;
*N_STO_P.fx(sto) = 0 ;


* open solve loops
loop(loop_res_share,

%res_share_constr%$ontext

%varying_co2_prices%phi_min_res = loop_res_share.val/100;

%varying_co2_prices%$ontext
c_var_con(ct) = tech_con_upload(ct,'fuel_costs')/tech_con_upload(ct,'eta_con')
         + tech_con_upload(ct,'carbon_content')/tech_con_upload(ct,'eta_con')*loop_res_share.val ;
$ontext
$offtext


solve DIETER_reduced using lp min Z ;


report_tech('capacities renewable GW',loop_res_share,res) = (0 + N_RENEWABLE.l(res)) / 1000 ;


*-------------------------------------------------------------------------------
*Report

*         report('infeasibility',loop_res_share) = sum( h , INFES.l(h) ) ;
         report('obj value',loop_res_share) = Z.l ;

%sc%             report('renshare',loop_res_share) = sum( (res,h) , G_RENEWABLE.l(res,h) ) / ( sum( h , d(h) ) + ( sum( (sto,h) , STO_IN.l(sto,h) - STO_OUT.l(sto,h) ) ) / phi_min_res ) ;
%not_sc%         report('renshare',loop_res_share) = sum( (res,h) , G_RENEWABLE.l(res,h) ) / ( sum( h , d(h) ) + sum( (sc,h) , SC_IN.l(sc,h) ) + ( sum( (sto,h) , STO_IN.l(sto,h) - STO_OUT.l(sto,h) ) ) / phi_min_res ) ;

*%sc%             report('conshare',loop_res_share) = sum( (ct,h) , G_CON.l(ct,h) ) / sum( h , d(h) ) ;
*%not_sc%         report('conshare',loop_res_share) = sum( (ct,h) , G_CON.l(ct,h) ) / ( sum( h , d(h) ) + (1-phi_min_res)*sum( sc , sc_flh(sc) * sc_power(sc) ) ) ;
*         report('renshare',loop_res_share) = 1-report('conshare',loop_res_share) ;
         report('conshare',loop_res_share) = 1-report('renshare',loop_res_share) ;
         report('hours with storing in and out in same period',loop_res_share) = sum( (sto,h)$(STO_IN.l(sto,h) > 0 AND STO_OUT.l(sto,h) > 0) , 1 ) ;
         report('peak load',loop_res_share) = smax( h , d(h) ) ;
         report('yearly load',loop_res_share) = sum( h , d(h) ) ;

         report_hours('demand',loop_res_share,'demand',h) = d(h) ;
         report_hours('generation conventional',loop_res_share,ct,h) =  G_CON.l(ct,h) ;
         report_hours('generation renewable',loop_res_share,res,h) = G_RENEWABLE.l(res,h) ;
         report_hours('curtailment of fluct res',loop_res_share,res,h) = CU.l(res,h) ;
         report_hours('generation storage',loop_res_share,sto,h) = STO_OUT.l(sto,h) ;
         report_hours('storage loading',loop_res_share,sto,h) = STO_IN.l(sto,h) ;
         report_hours('storage level',loop_res_share,sto,h) = STO_L.l(sto,h) ;
         report_hours('storage level relative',loop_res_share,sto,h) = STO_L.l(sto,h) / report('yearly load',loop_res_share) ;
%not_sc% report_hours('sc loading',loop_res_share,sc,h) = SC_IN.l(sc,h) ;

         report_hours('wholesale prices',loop_res_share,'prices',h) = energy_balance.m(h) ;

         report_hours('residual load GW',loop_res_share,'RL (before sc and curt and sto)',h) = (d(h) - sum( res , phi_res(res,h) * N_RENEWABLE.l(res)) ) / 1000 ;
%sc%     report_hours('residual load GW',loop_res_share,'RL (after curt)',h) = (d(h) - sum( res , phi_res(res,h) * N_RENEWABLE.l(res) - CU.l(res,h)) ) / 1000 ;
%sc%     report_hours('residual load GW',loop_res_share,'RL (after curt and sto)',h) = (d(h) - sum( res , phi_res(res,h) * N_RENEWABLE.l(res) - CU.l(res,h)) - sum( sto , STO_OUT.l(sto,h) - STO_IN.l(sto,h)) ) / 1000 ;
%not_sc% report_hours('residual load GW',loop_res_share,'RL (after sc)',h) =  (d(h) - sum( res , phi_res(res,h) * N_RENEWABLE.l(res)) + sum( sc , SC_IN.l(sc,h)) ) / 1000 ;
%not_sc% report_hours('residual load GW',loop_res_share,'RL (after sc and curt)',h) =  (d(h) - sum( res , phi_res(res,h) * N_RENEWABLE.l(res) - CU.l(res,h)) + sum( sc , SC_IN.l(sc,h)) ) / 1000 ;
%not_sc% report_hours('residual load GW',loop_res_share,'RL (after sc and curt and sto in)',h) = (d(h) - sum( res , phi_res(res,h) * N_RENEWABLE.l(res) - CU.l(res,h)) - sum( sto , - STO_IN.l(sto,h)) + sum( sc , SC_IN.l(sc,h)) ) / 1000 ;
%not_sc% report_hours('residual load GW',loop_res_share,'RL (after sc and curt and sto)',h) = (d(h) - sum( res , phi_res(res,h) * N_RENEWABLE.l(res) - CU.l(res,h)) - sum( sto , STO_OUT.l(sto,h) - STO_IN.l(sto,h)) + sum( sc , SC_IN.l(sc,h)) ) / 1000 ;
%not_sc% report_hours('residual load GW',loop_res_share,'RL (aux storage out for graph)',h) = min( report_hours('residual load GW',loop_res_share,'RL (before sc and curt and sto)',h)$(report_hours('residual load GW',loop_res_share,'RL (before sc and curt and sto)',h) > 0) , report_hours('residual load GW',loop_res_share,'RL (after sc and curt and sto in)',h) ) ;
%not_sc% report_hours('residual load GW',loop_res_share,'RL (aux conv gen for graph)',h) = min( report_hours('residual load GW',loop_res_share,'RL (before sc and curt and sto)',h)$(report_hours('residual load GW',loop_res_share,'RL (before sc and curt and sto)',h) > 0 ) , report_hours('residual load GW',loop_res_share,'RL (after sc and curt and sto)',h) ) ;

         report_hours('residual load relative',loop_res_share,'RL (before sc and curt and sto)',h) = report_hours('residual load GW',loop_res_share,'RL (before sc and curt and sto)',h) * 1000 / report('peak load',loop_res_share) ;
%sc%     report_hours('residual load relative',loop_res_share,'RL (after curt)',h) = report_hours('residual load GW',loop_res_share,'RL (after curt)',h) * 1000 / report('peak load',loop_res_share) ;
%sc%     report_hours('residual load relative',loop_res_share,'RL (after curt and sto)',h) = report_hours('residual load GW',loop_res_share,'RL (after curt and sto)',h) * 1000 / report('peak load',loop_res_share) ;
%not_sc% report_hours('residual load relative',loop_res_share,'RL (after sc)',h) = report_hours('residual load GW',loop_res_share,'RL (after sc)',h) * 1000 / report('peak load',loop_res_share) ;
%not_sc% report_hours('residual load relative',loop_res_share,'RL (after sc and curt)',h) = report_hours('residual load GW',loop_res_share,'RL (after sc and curt)',h) * 1000 / report('peak load',loop_res_share) ;
%not_sc% report_hours('residual load relative',loop_res_share,'RL (after sc and curt and sto in)',h) = report_hours('residual load GW',loop_res_share,'RL (after sc and curt and sto in)',h) * 1000 / report('peak load',loop_res_share) ;
%not_sc% report_hours('residual load relative',loop_res_share,'RL (after sc and curt and sto)',h) = report_hours('residual load GW',loop_res_share,'RL (after sc and curt and sto)',h) * 1000 / report('peak load',loop_res_share) ;
%not_sc% report_hours('residual load relative',loop_res_share,'RL (aux storage out for graph)',h) = report_hours('residual load GW',loop_res_share,'RL (aux storage out for graph)',h) * 1000 / report('peak load',loop_res_share) ;
%not_sc% report_hours('residual load relative',loop_res_share,'RL (aux conv gen for graph)',h) = report_hours('residual load GW',loop_res_share,'RL (aux conv gen for graph)',h) * 1000 / report('peak load',loop_res_share) ;

                 report_hours('residual load GW',loop_res_share,'RL (before sc and curt and sto)',h)$(report_hours('residual load GW',loop_res_share,'RL (before sc and curt and sto)',h) = 0) = 0.001 ;
%sc%             report_hours('residual load GW',loop_res_share,'RL (after curt)',h)$(report_hours('residual load GW',loop_res_share,'RL (after curt)',h) = 0) = 0.001 ;
%sc%             report_hours('residual load GW',loop_res_share,'RL (after curt and sto)',h)$(report_hours('residual load GW',loop_res_share,'RL (after curt and sto)',h) = 0) = 0.001 ;
%not_sc%         report_hours('residual load GW',loop_res_share,'RL (after sc)',h)$(report_hours('residual load GW',loop_res_share,'RL (after sc)',h) = 0) = 0.001 ;
%not_sc%         report_hours('residual load GW',loop_res_share,'RL (after sc and curt)',h)$(report_hours('residual load GW',loop_res_share,'RL (after sc and curt)',h) = 0) = 0.001 ;
%not_sc%         report_hours('residual load GW',loop_res_share,'RL (after sc and curt and sto in)',h)$(report_hours('residual load GW',loop_res_share,'RL (after sc and curt and sto in)',h) = 0) = 0.001 ;
%not_sc%         report_hours('residual load GW',loop_res_share,'RL (after sc and curt and sto)',h)$(report_hours('residual load GW',loop_res_share,'RL (after sc and curt and sto)',h) = 0) = 0.001 ;
%not_sc%         report_hours('residual load GW',loop_res_share,'RL (aux storage out for graph)',h)$(report_hours('residual load GW',loop_res_share,'RL (aux storage out for graph)',h) = 0) = 0.001 ;
%not_sc%         report_hours('residual load GW',loop_res_share,'RL (aux conv gen for graph)',h)$(report_hours('residual load GW',loop_res_share,'RL (aux conv gen for graph)',h) = 0) = 0.001 ;

                 report_hours('residual load relative',loop_res_share,'RL (before sc and curt and sto)',h)$(report_hours('residual load relative',loop_res_share,'RL (before sc and curt and sto)',h) = 0) = 0.00001 ;
%sc%             report_hours('residual load relative',loop_res_share,'RL (after curt)',h)$(report_hours('residual load relative',loop_res_share,'RL (after curt)',h) = 0) = 0.00001 ;
%sc%             report_hours('residual load relative',loop_res_share,'RL (after curt and sto)',h)$(report_hours('residual load relative',loop_res_share,'RL (after curt and sto)',h) = 0) = 0.00001 ;
%not_sc%         report_hours('residual load relative',loop_res_share,'RL (after sc)',h)$(report_hours('residual load relative',loop_res_share,'RL (after sc)',h) = 0) = 0.00001 ;
%not_sc%         report_hours('residual load relative',loop_res_share,'RL (after sc and curt)',h)$(report_hours('residual load relative',loop_res_share,'RL (after sc and curt)',h) = 0) = 0.00001 ;
%not_sc%         report_hours('residual load relative',loop_res_share,'RL (after sc and curt and sto in)',h)$(report_hours('residual load relative',loop_res_share,'RL (after sc and curt and sto in)',h) = 0) = 0.00001 ;
%not_sc%         report_hours('residual load relative',loop_res_share,'RL (after sc and curt and sto)',h)$(report_hours('residual load relative',loop_res_share,'RL (after sc and curt and sto)',h) = 0) = 0.00001 ;
%not_sc%         report_hours('residual load relative',loop_res_share,'RL (aux storage out for graph)',h)$(report_hours('residual load relative',loop_res_share,'RL (aux storage out for graph)',h) = 0) = 0.00001 ;
%not_sc%         report_hours('residual load relative',loop_res_share,'RL (aux conv gen for graph)',h)$(report_hours('residual load relative',loop_res_share,'RL (aux conv gen for graph)',h) = 0) = 0.00001 ;

                 report_hours('storage level relative',loop_res_share,sto,h)$(report_hours('storage level relative',loop_res_share,sto,h) = 0) = 0.0000001 ;

         report_tech('capacities renewable GW',loop_res_share,res) = (0 + N_RENEWABLE.l(res)) / 1000 ;
         report_tech('capacities storage GWh',loop_res_share,sto) = N_STO_E.l(sto) / 1000 ;
         report_tech('capacities storage GW',loop_res_share,sto) = N_STO_P.l(sto) / 1000 ;
         report_tech('capacities conventional GW',loop_res_share,ct) = (0 + N_CON.l(ct)) / 1000 ;

         report_tech('EP ratio storage',loop_res_share,sto)$report_tech('capacities storage GW',loop_res_share,sto) = report_tech('capacities storage GWh',loop_res_share,sto) / report_tech('capacities storage GW',loop_res_share,sto) ;
         report_tech('storage FLH',loop_res_share,sto)$N_STO_P.l(sto) = sum( h , STO_OUT.l(sto,h)) / N_STO_P.l(sto) ;
         report_tech('storage cycles',loop_res_share,sto)$N_STO_E.l(sto) = sum( h , STO_OUT.l(sto,h)) / N_STO_E.l(sto) ;
         report_tech('yearly storage level over generation',loop_res_share,sto)$(N_STO_E.l(sto)) = sum( h , STO_L.l(sto,h) ) / sum( h , STO_OUT.l(sto,h) ) ;
         report_tech('renewables curtailed absolute',loop_res_share,res) =  sum(h, CU.l(res,h) ) ;
         report_tech('renewables curtailed relative',loop_res_share,res)$(report_tech('renewables curtailed absolute',loop_res_share,res)) =  sum(h, CU.l(res,h)) / sum(h , phi_res(res,h)*N_RENEWABLE.l(res) ) ;

         report_tech('capacities renewable relative',loop_res_share,res) = report_tech('capacities renewable GW',loop_res_share,res) * 1000 / report('peak load',loop_res_share) ;
         report_tech('capacities storage energy relative',loop_res_share,sto) = report_tech('capacities storage GWh',loop_res_share,sto) * 1000 / report('yearly load',loop_res_share) ;
         report_tech('capacities storage power relative',loop_res_share,sto) = report_tech('capacities storage GW',loop_res_share,sto) * 1000 / report('peak load',loop_res_share) ;
         report_tech('capacities conventional relative',loop_res_share,ct) = report_tech('capacities conventional GW',loop_res_share,ct) * 1000 / report('peak load',loop_res_share) ;

         report('capacities renewable relative',loop_res_share) = sum( res , report_tech('capacities renewable relative',loop_res_share,res) ) ;
         report('capacities storage energy relative',loop_res_share) = sum( sto , report_tech('capacities storage energy relative',loop_res_share,sto) ) ;
         report('capacities storage power relative',loop_res_share) = sum( sto , report_tech('capacities storage power relative',loop_res_share,sto) ) ;
         report('capacities conventional relative',loop_res_share) = sum( ct , report_tech('capacities conventional relative',loop_res_share,ct) ) ;

%not_sc% report_tech('sc flh',loop_res_share,sc) = sum( h , SC_IN.l(sc,h)) / sc_power(sc) ;
%not_sc% report_tech('sc power GW',loop_res_share,sc) = sc_power(sc) / 1000 ;
%not_sc% report_tech('sc demand TWh',loop_res_share,sc) = %sc_dem%/100 * sum( h , d(h) ) / 1000000 ;

%not_sc% report_tech('sc power relative',loop_res_share,sc) = report_tech('sc power GW',loop_res_share,sc) * 1000 / report('peak load',loop_res_share) ;
%not_sc% report_tech('sc demand relative',loop_res_share,sc) = report_tech('sc demand TWh',loop_res_share,sc) * 1000000 / report('yearly load',loop_res_share) ;

         report_tech('market value of renewable generation',loop_res_share,res)$(N_RENEWABLE.l(res)) = sum( h, energy_balance.m(h) * G_RENEWABLE.l(res,h) ) / sum( h, G_RENEWABLE.l(res,h) ) ;
         report_tech('market value of renewable generation + dual',loop_res_share,res)$(N_RENEWABLE.l(res)) = sum( h, (energy_balance.m(h) + renewable_share.m) * G_RENEWABLE.l(res,h) ) / sum( h, G_RENEWABLE.l(res,h) ) ;
         report_tech('check zero profit RES',loop_res_share,res)$(N_RENEWABLE.l(res)) = sum( h, energy_balance.m(h) * G_RENEWABLE.l(res,h) ) - c_i_res(res) * N_RENEWABLE.l(res) ;
         report_tech('check zero profit RES',loop_res_share,res)$(N_RENEWABLE.l(res)) = sum( h, (energy_balance.m(h) + renewable_share.m) * G_RENEWABLE.l(res,h) ) - c_i_res(res) * N_RENEWABLE.l(res) ;
         report_tech('market value of conventional generation',loop_res_share,ct)$(N_CON.l(ct)) = sum( h, energy_balance.m(h) * G_CON.l(ct,h) ) / sum( h, G_CON.l(ct,h) ) ;
         report_tech('check zero profit CON',loop_res_share,ct)$(N_CON.l(ct)) = sum( h, (energy_balance.m(h) - c_var_con(ct)) * G_CON.l(ct,h) ) - c_i_con(ct) * N_CON.l(ct) ;
         report_tech('check zero profit STO',loop_res_share,sto)$(N_STO_E.l(sto)) = sum( h, (energy_balance.m(h) - c_var_sto(sto)) * STO_OUT.l(sto,h) )
                                                                                  - sum( h, (energy_balance.m(h) + c_var_sto(sto)) * STO_IN.l(sto,h) )
                                                                                  - sum( h, renewable_share.m  * ( STO_IN.l(sto,h) - STO_OUT.l(sto,h)) )
                                                                                  - c_i_sto_e(sto) * N_STO_E.l(sto) - c_i_sto_p(sto) * N_STO_P.l(sto) ;

         report_tech('LCOE of renewable generation',loop_res_share,res)$(N_RENEWABLE.l(res)) = c_i_res(res) * N_RENEWABLE.l(res) / sum( h, G_RENEWABLE.l(res,h)) ;

         report_tech('LCOE of conventional generation',loop_res_share,ct)$(N_CON.l(ct)) = (c_i_con(ct) * N_CON.l(ct) + sum( h , c_var_con(ct) * G_CON.l(ct,h) ) ) / sum( h, G_CON.l(ct,h)) ;

         report('unweighted average price',loop_res_share) = sum( h, energy_balance.m(h)) / 8760 ;
         report('weighted average price',loop_res_share) = sum( h, energy_balance.m(h) * ( d(h)
%not_sc%         + sum( sc , SC_IN.l(sc,h))
         ) ) / sum( h, d(h) + sum( sto , STO_IN.l(sto,h))
%not_sc%         + sum( sc , SC_IN.l(sc,h))
         );

         report('dual of renewable share constraint',loop_res_share) = renewable_share.m ;

         report_tech('market value of storage',loop_res_share,sto)$(N_STO_E.l(sto)) = sum( h, energy_balance.m(h) * ( STO_OUT.l(sto,h)-STO_IN.l(sto,h) ) ) / sum( h, STO_OUT.l(sto,h) ) ;
         report_tech('market value of storage - levy',loop_res_share,sto)$(N_STO_E.l(sto)) = report_tech('market value of storage',loop_res_share,sto)
                                                            - renewable_share.m * sum(h, STO_IN.l(sto,h)-STO_OUT.l(sto,h))/ sum(h,STO_OUT.l(sto,h)) ;

         report_tech('LCOS',loop_res_share,sto)$(N_STO_E.l(sto)) = ( c_i_sto_e(sto) * N_STO_E.l(sto) + c_i_sto_p(sto) * N_STO_P.l(sto) + sum( h, c_var_sto(sto)*(STO_IN.l(sto,h)+STO_OUT.l(sto,h)) ) ) / sum( h, STO_OUT.l(sto,h)) ;

* close solve loop
);


Execute_Unload 'results_%base_year%%report_sc%', report, report_tech, report_hours ;
