Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Genie leos dev #690

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions message_ix/model/MESSAGE/data_load.gms
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ Set rating_unrated(rating) ;
rating_unrated(rating) = yes ;
rating_unrated('unrated') = no ;

* this is a temporary data for learning technologies. this need to be made automatic
Set newtec(tec) / wind_ppl / ;

*----------------------------------------------------------------------------------------------------------------------*
* assignment and computation of MESSAGE-specific auxiliary parameters *
*----------------------------------------------------------------------------------------------------------------------*
Expand Down
68 changes: 68 additions & 0 deletions message_ix/model/MESSAGE/model_learningeos.gms
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
Sets
size 'size' / small, medium, large / ;

Alias (size,size2);
Parameters
cap_new2(node,newtec,year_all2) 'annual newly installed capacity'
rho(newtec) 'economy of scale parameter'
/ wind_ppl 1 / #0.8
b(newtec) 'technology cost learning parameter'
/ wind_ppl 0.9 / #0.9
u(size) 'unit size'
/ small 5
medium 10
large 50 /
inv_cost0(node,newtec) 'initial capex'
n_unit0(newtec) 'initial number of unit'
/ wind_ppl 100 /
u0(newtec) 'reference size'
/ wind_ppl 5 / ;
inv_cost0(node,newtec)=1500;

scalar hist_length the length of historical periods;
hist_length = card(year_all2) - card(model_horizon);

*Table
* cap_new2(node,newtec,year_all2) 'annual newly installed capacity'
* 690 700 710 720
* Westeros.wind_ppl 100 10 0 0 ;

Variables
N_unit(node,newtec,size,year_all2) number of units for each size every year
CapexTec(node,newtec,year_all2) capital cost in dollar per kW
Object objective function ;

Positive Variables
N_unit;

Equations
Objective_inner total investment cost
C_balance installed capacity balance
Capex_estimate estimating average capex
Annual_investment annual investment cost
;


Objective_inner.. Object =e= sum((node,newtec,year_all2), CapexTec(node,newtec,year_all2)*cap_new2(node,newtec,year_all2)) ;
C_balance(node,newtec,year_all2).. sum(size, N_unit(node,newtec,size,year_all2)*u(size)) =e= cap_new2(node,newtec,year_all2) ;
Capex_estimate(node,newtec,year_all2).. CapexTec(node,newtec,year_all2)*cap_new2(node,newtec,year_all2) =g= sum(size,inv_cost0(node,newtec)
*N_unit(node,newtec,size,year_all2)*u(size)
*[(((sum((size2,year_all3)$(ord(year_all3) le ord(year_all2) and ord(year_all3) gt hist_length), N_unit(node,newtec,size2,year_all3))+n_unit0(newtec))/n_unit0(newtec))**(-b(newtec)))]
*[((u(size)/u0(newtec))**rho(newtec))]) ;
Annual_investment(node,newtec,year_all2).. sum(year_all3$(ord(year_all3) le ord(year_all2) and ord(year_all3) gt hist_length), CapexTec(node,newtec,year_all3)*cap_new2(node,newtec,year_all3))
- sum(year_all3$(ord(year_all3) le (ord(year_all2)-1) and ord(year_all3) gt hist_length), CapexTec(node,newtec,year_all3)*cap_new2(node,newtec,year_all3)) =g= 0 ;

model leaningeos / all /;

$ontext

Objective_inner.. Object =e= sum((node,newtec,year_all2), CapexTec(node,newtec,year_all2)*cap_new2(node,newtec,year_all2)) ;
C_balance(node,newtec,year_all2).. sum(size, N_unit(node,newtec,size,year_all2)*u(size)) =e= cap_new2(node,newtec,year_all2) ;
Capex_estimate(node,newtec,year_all2).. CapexTec(node,newtec,year_all2)*cap_new2(node,newtec,year_all2) =g= sum(size,inv_cost0(node,newtec)
*N_unit(node,newtec,size,year_all2)*u(size)
*[(((sum((size2,year_all3)$(ord(year_all3) le ord(year_all2) and ord(year_all3) gt hist_length), N_unit(node,newtec,size2,year_all3))+n_unit0(newtec))/n_unit0(newtec))**(-b(newtec)))]
*[((u(size)/u0(newtec))**rho(newtec))]) ;

model leaningeos / all /;

$offtext
1 change: 1 addition & 0 deletions message_ix/model/MESSAGE/model_setup.gms
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,4 @@ $INCLUDE MESSAGE/scaling_investment_costs.gms
*----------------------------------------------------------------------------------------------------------------------*

$INCLUDE MESSAGE/model_core.gms
$INCLUDE MESSAGE/model_learningeos.gms
143 changes: 115 additions & 28 deletions message_ix/model/MESSAGE/model_solve.gms
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,81 @@ EMISSION_CONSTRAINT.m(node,type_emission,type_tec,type_year)$(
%AUX_BOUNDS% AUX_ACT_BOUND_UP(node,tec,year_all,year_all2,mode,time)$( ACT.l(node,tec,year_all,year_all2,mode,time) > 0 AND
%AUX_BOUNDS% ACT.l(node,tec,year_all,year_all2,mode,time) = %AUX_BOUND_VALUE% ) = yes ;



elseif %foresight% = -1,
***
* Recursive-dynamic and myopic model
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* For the myopic and rolling-horizon models, loop over horizons and iteratively solve the model, keeping the decision
* variables from prior periods fixed.
* This option is selected by setting the GAMS global variable ``%foresight%`` to a value greater than 0,
* where the value represents the number of years that the model instance is considering when iterating over the periods
* of the optimization horizon.
*
* Loop over :math:`\hat{y} \in Y`, solving
*
* .. math::
* \min_x \ OBJ = \sum_{y \in \hat{Y}(\hat{y})} OBJ_y(x_y) \\
* \text{s.t. } x_{y'} = x_{y'}^* \quad \forall \ y' < y
*
* where :math:`\hat{Y}(\hat{y}) = \{y \in Y | \ |\hat{y}| - |y| < optimization\_horizon \}` and
* :math:`x_{y'}^*` is the optimal value of :math:`x_{y'}` in iteration :math:`|y'|` of the iterative loop.
*
* The advantage of this implementation is that there is no need to 'store' the optimal values of all decision
* variables in additional reporting parameters - the last model solve automatically includes the results over the
* entire model horizon and can be imported via the ixmp interface.
***
year(year_all) = no ;
year(model_horizon) = yes ;
LOOP(year_all$( model_horizon(year_all) ),

* year(model_horizon) = yes ;
year4(year_all2)$((ord(year_all2) < ord(year_all))) = yes ;
*
option threads = 4 ;
Solve MESSAGE_LP using LP minimizing OBJ ;
* write model status summary
status('perfect_foresight','modelstat') = MESSAGE_LP.modelstat ;
status('perfect_foresight','solvestat') = MESSAGE_LP.solvestat ;
status('perfect_foresight','resUsd') = MESSAGE_LP.resUsd ;
status('perfect_foresight','objEst') = MESSAGE_LP.objEst ;
status('perfect_foresight','objVal') = MESSAGE_LP.objVal ;

* write an error message if model did not solve to optimality
IF( NOT ( MESSAGE_LP.modelstat = 1 OR MESSAGE_LP.modelstat = 8 ),
put_utility 'log' /'+++ MESSAGEix did not solve to optimality - run is aborted, no output produced! +++ ' ;
ABORT "MESSAGEix did not solve to optimality!"
) ;

* passing CAP_NEW values to update cap_new2 data for unit and size optimization
cap_new2(node,newtec,year_all2) = CAP_NEW.l(node,newtec,year_all2);
display cap_new2;

solve leaningeos using nlp minimizing Object;
* passing CapexTec values to update inv_cost data for MESSAGE optimization
inv_cost(node,newtec,year_all) = CapexTec.l(node,newtec,year_all);

Execute_unload 'learningeos.gdx',N_unit,CapexTec,cap_new2, CAP_NEW.l, cap_new2;;

* fix all variables of the current iteration period 'year_all' to the optimal levels
EXT.fx(node,commodity,grade,year4) = EXT.l(node,commodity,grade,year4) ;
CAP_NEW.fx(node,tec,year4) = CAP_NEW.l(node,tec,year4) ;
CAP.fx(node,tec,year4,year4) = CAP.l(node,tec,year4,year4) ;
ACT.fx(node,tec,year4,year4,mode,time) = ACT.l(node,tec,year4,year4,mode,time) ;
CAP_NEW_UP.fx(node,tec,year4) = CAP_NEW_UP.l(node,tec,year4) ;
CAP_NEW_LO.fx(node,tec,year4) = CAP_NEW_LO.l(node,tec,year4) ;
ACT_UP.fx(node,tec,year4,time) = ACT_UP.l(node,tec,year4,time) ;
ACT_LO.fx(node,tec,year4,time) = ACT_LO.l(node,tec,year4,time) ;


Display year,year4,year_all,model_horizon,CapexTec.l,hist_length ;
) ; # end of the recursive-dynamic loop for technology cost learning and economy of scale module





else
***
* Recursive-dynamic and myopic model
Expand Down Expand Up @@ -93,41 +168,53 @@ else
LOOP(year_all$( model_horizon(year_all) ),

* include all past periods and future periods including the period where the %foresight% is reached
year(year_all) = yes ;
* year(year_all) = yes ;
year(year_all2)$( ORD(year_all2) < (ORD(year_all) + %foresight%) ) = yes ;
year4(year_all2)$((ord(year_all2) < ord(year_all))) = yes ;

* reset the investment cost scaling parameter
year(year_all2)$( ORD(year_all2) > ORD(year_all)
AND duration_period_sum(year_all,year_all2) < %foresight% ) = yes ;
* year(year_all2)$( ORD(year_all2) > ORD(year_all)
* AND duration_period_sum(year_all,year_all2) < %foresight% ) = yes ;

* write a status update and time elapsed to the log file, solve the model
put_utility 'log' /'+++ Solve the recursive-dynamic version of MESSAGEix - iteration ' year_all.tl:0 ' +++ ' ;
$$INCLUDE includes/aux_computation_time.gms
Solve MESSAGE_LP using LP minimizing OBJ ;

* write model status summary
status(year_all,'modelstat') = MESSAGE_LP.modelstat ;
status(year_all,'solvestat') = MESSAGE_LP.solvestat ;
status(year_all,'resUsd') = MESSAGE_LP.resUsd ;
status(year_all,'objEst') = MESSAGE_LP.objEst ;
status(year_all,'objVal') = MESSAGE_LP.objVal ;

* write an error message AND ABORT THE SOLVE LOOP if model did not solve to optimality
IF( NOT ( MESSAGE_LP.modelstat = 1 OR MESSAGE_LP.modelstat = 8 ),
put_utility 'log' /'+++ MESSAGEix did not solve to optimality - run is aborted, no output produced! +++ ' ;
ABORT "MESSAGEix did not solve to optimality!"
) ;
option threads = 4 ;
Solve MESSAGE_LP using LP minimizing OBJ ;
* write model status summary
status('perfect_foresight','modelstat') = MESSAGE_LP.modelstat ;
status('perfect_foresight','solvestat') = MESSAGE_LP.solvestat ;
status('perfect_foresight','resUsd') = MESSAGE_LP.resUsd ;
status('perfect_foresight','objEst') = MESSAGE_LP.objEst ;
status('perfect_foresight','objVal') = MESSAGE_LP.objVal ;

* write an error message if model did not solve to optimality
IF( NOT ( MESSAGE_LP.modelstat = 1 OR MESSAGE_LP.modelstat = 8 ),
put_utility 'log' /'+++ MESSAGEix did not solve to optimality - run is aborted, no output produced! +++ ' ;
ABORT "MESSAGEix did not solve to optimality!"
) ;

IF(%learningmode% = 1,
* passing CAP_NEW values to update cap_new2 data for unit and size optimization
cap_new2(node,newtec,year_all2) = CAP_NEW.l(node,newtec,year_all2);
display cap_new2;

solve leaningeos using nlp minimizing Object;
* passing CapexTec values to update inv_cost data for MESSAGE optimization
inv_cost(node,newtec,year_all) = CapexTec.l(node,newtec,year_all);

Execute_unload 'learningeos.gdx',N_unit,CapexTec,cap_new2, CAP_NEW.l, cap_new2;;
);
* fix all variables of the current iteration period 'year_all' to the optimal levels
EXT.fx(node,commodity,grade,year_all) = EXT.l(node,commodity,grade,year_all) ;
CAP_NEW.fx(node,tec,year_all) = CAP_NEW.l(node,tec,year_all) ;
CAP.fx(node,tec,year_all2,year_all)$( map_period(year_all2,year_all) ) = CAP.l(node,tec,year_all,year_all2) ;
ACT.fx(node,tec,year_all2,year_all,mode,time)$( map_period(year_all2,year_all) )
= ACT.l(node,tec,year_all2,year_all,mode,time) ;
CAP_NEW_UP.fx(node,tec,year_all) = CAP_NEW_UP.l(node,tec,year_all) ;
CAP_NEW_LO.fx(node,tec,year_all) = CAP_NEW_LO.l(node,tec,year_all) ;
ACT_UP.fx(node,tec,year_all,time) = ACT_UP.l(node,tec,year_all,time) ;
ACT_LO.fx(node,tec,year_all,time) = ACT_LO.l(node,tec,year_all,time) ;
EXT.fx(node,commodity,grade,year4) = EXT.l(node,commodity,grade,year4) ;
CAP_NEW.fx(node,tec,year4) = CAP_NEW.l(node,tec,year4) ;
CAP.fx(node,tec,year4,year4) = CAP.l(node,tec,year4,year4) ;
ACT.fx(node,tec,year4,year4,mode,time) = ACT.l(node,tec,year4,year4,mode,time) ;
CAP_NEW_UP.fx(node,tec,year4) = CAP_NEW_UP.l(node,tec,year4) ;
CAP_NEW_LO.fx(node,tec,year4) = CAP_NEW_LO.l(node,tec,year4) ;
ACT_UP.fx(node,tec,year4,time) = ACT_UP.l(node,tec,year4,time) ;
ACT_LO.fx(node,tec,year4,time) = ACT_LO.l(node,tec,year4,time) ;


Display year,year4,year_all,model_horizon,CapexTec.l,hist_length ;
) ; # end of the recursive-dynamic loop

) ; # end of if statement for the selection betwen perfect-foresight or recursive-dynamic model
Expand Down
38 changes: 20 additions & 18 deletions message_ix/model/MESSAGE/sets_maps_def.gms
Original file line number Diff line number Diff line change
Expand Up @@ -140,24 +140,26 @@ $ONEMPTY
***

Sets
node world - regions - countries - grid cells
commodity resources - electricity - water - land availability - etc.
level levels of the reference energy system or supply chain ( primary - secondary - ... - useful )
sector sectors (for integration with MACRO)
grade grades of extraction of raw materials
tec technologies
mode modes of operation
emission greenhouse gases - pollutants - etc.
land_scenario scenarios of land use (for land-use model emulator)
land_type types of land use
year_all years (over entire model horizon)
year (year_all) years included in a model instance (for myopic or rolling-horizon optimization)
time subannual time periods (seasons - days - hours)
shares share constraint relations
relation generic linear relations
lvl_spatial hierarchical levels of spatial resolution
lvl_temporal hierarchical levels of temporal resolution
rating identifies the 'quality' of the renewable energy potential (bins acc. to Sullivan)
node world - regions - countries - grid cells
commodity resources - electricity - water - land availability - etc.
level levels of the reference energy system or supply chain ( primary - secondary - ... - useful )
sector sectors (for integration with MACRO)
grade grades of extraction of raw materials
tec technologies
mode modes of operation
emission greenhouse gases - pollutants - etc.
land_scenario scenarios of land use (for land-use model emulator)
land_type types of land use
year_all years (over entire model horizon)
year (year_all) years included in a model instance (for myopic or rolling-horizon optimization)
year4 (year_all) years included in a model instance (for myopic or rolling-horizon optimization)
year_hist (year_all) historical year
time subannual time periods (seasons - days - hours)
shares share constraint relations
relation generic linear relations
lvl_spatial hierarchical levels of spatial resolution
lvl_temporal hierarchical levels of temporal resolution
rating identifies the 'quality' of the renewable energy potential (bins acc. to Sullivan)
;

* definition of aliases
Expand Down
5 changes: 5 additions & 0 deletions message_ix/model/MESSAGE_master.gms
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ $SETGLOBAL macromode "none"
* rolling horizon (period-by-period, recursive-dynamic with limited foresight - 'number of years of foresight'
$SETGLOBAL foresight "0"

** for recursive dynamic approach, this is to activate/deactivate technology learning module **
* deactivate technology learning - 0
* activate technology learning - 1
$SETGLOBAL learningmode "0"

** add a comment and name extension for model report files (e.g. run-specific info, calibration notes) - optional **
$SETGLOBAL comment ""

Expand Down