Skip to content

Commit

Permalink
Refactor the calculation of PRICE_EMISSION and remove PRICE_EMISSION_NEW
Browse files Browse the repository at this point in the history
  • Loading branch information
behnam-zakeri committed Apr 11, 2024
1 parent e850b8e commit 41c5dd1
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 39 deletions.
9 changes: 1 addition & 8 deletions message_ix/model/MESSAGE/model_core.gms
Original file line number Diff line number Diff line change
Expand Up @@ -135,25 +135,18 @@ Variables
* Variable Explanatory text
* ======================================================================================= =======================================================================================================
* :math:`\text{DEMAND}_{n,c,l,y,h} \in \mathbb{R}` Demand level (in equilibrium with MACRO integration)
* :math:`\text{EMISSION_CONSTRAINT_RESCALE}_{n,\widehat{e},\widehat{t},y} \in \mathbb{R}` Annual average marginal of :ref:`emission_constraint`
* :math:`\text{PRICE_COMMODITY}_{n,c,l,y,h} \in \mathbb{R}` Commodity price (undiscounted marginals of :ref:`commodity_balance_gt` and :ref:`commodity_balance_lt`)
* :math:`\text{PRICE_EMISSION}_{n,\widehat{e},\widehat{t},y} \in \mathbb{R}` Emission price (undiscounted marginals of :ref:`emission_constraint`)
* :math:`\text{COST_NODAL_NET}_{n,y} \in \mathbb{R}` System costs at the node level net of energy trade revenues/cost
* :math:`\text{GDP}_{n,y} \in \mathbb{R}` Gross domestic product (GDP) in market exchange rates for MACRO reporting
* ======================================================================================= =======================================================================================================
*
* .. warning::
* Please be aware that transitioning from one period length to another for consecutive periods may result in false values of :math:`\text{PRICE_EMISSION}`.
* Please see `this issue <https://github.com/iiasa/message_ix/issues/723>`_ for further information. We are currently working on a fix.
***

Variables
* auxiliary variables for demand, prices, costs and GDP (for reporting when MESSAGE is run with MACRO)
DEMAND(node,commodity,level,year_all,time) demand
EMISSION_CONSTRAINT_RESCALE(node,type_emission,type_tec,type_year) rescaled of marginals of EMISSION_CONSTRAINT constraint
PRICE_COMMODITY(node,commodity,level,year_all,time) commodity price (derived from marginals of COMMODITY_BALANCE constraint)
PRICE_EMISSION(node,type_emission,type_tec,year_all) emission price (derived from marginals of EMISSION_BOUND constraint)
PRICE_EMISSION_NEW(node,type_emission,type_tec,year_all) emission price (derived from marginals of EMISSION_EQUIVALENCE constraint)
PRICE_EMISSION(node,type_emission,type_tec,year_all) emission price (derived from marginals of EMISSION_EQUIVALENCE constraint)
COST_NODAL_NET(node,year_all) system costs at the node level over time including effects of energy trade
GDP(node,year_all) gross domestic product (GDP) in market exchange rates for MACRO reporting
;
Expand Down
29 changes: 9 additions & 20 deletions message_ix/model/MESSAGE/model_solve.gms
Original file line number Diff line number Diff line change
Expand Up @@ -39,34 +39,23 @@ if (%foresight% = 0,
ABORT "MESSAGEix did not solve to optimality!"
) ;

* rescale the dual of the emission constraint to account that the constraint is defined on the average year, not total
EMISSION_CONSTRAINT_RESCALE.l(node,type_emission,type_tec,type_year)$(
EMISSION_CONSTRAINT.m(node,type_emission,type_tec,type_year) ) =
EMISSION_CONSTRAINT.m(node,type_emission,type_tec,type_year)
/ SUM(year$( cat_year(type_year,year) ), duration_period(year) )
;


* assign auxiliary variables DEMAND, PRICE_COMMODITY and PRICE_EMISSION for integration with MACRO and reporting
* assign auxiliary variables DEMAND for integration with MACRO
DEMAND.l(node,commodity,level,year,time) = demand_fixed(node,commodity,level,year,time) ;

* assign auxiliary variables PRICE_COMMODITY and PRICE_EMISSION for reporting
PRICE_COMMODITY.l(node,commodity,level,year,time) =
( COMMODITY_BALANCE_GT.m(node,commodity,level,year,time) + COMMODITY_BALANCE_LT.m(node,commodity,level,year,time) )
/ df_period(year) ;
PRICE_EMISSION.l(node,type_emission,type_tec,year)$( SUM(type_year$( cat_year(type_year,year) ), 1 ) ) =
SMAX(type_year$( cat_year(type_year,year) ),
- EMISSION_CONSTRAINT_RESCALE.l(node,type_emission,type_tec,type_year) )
/ df_period(year) * duration_period(year);
PRICE_EMISSION.l(node,type_emission,type_tec,year)$(
PRICE_EMISSION.l(node,type_emission,type_tec,year) = - inf ) = 0 ;
* Calculate PRICE_EMISSION based on the marginals of EMISSION_EQUIVALENCE
PRICE_EMISSION_NEW.l(node,type_emission,type_tec,year)$( SUM(emission$( cat_emission(type_emission,emission) ),

* calculate PRICE_EMISSION based on the marginals of EMISSION_EQUIVALENCE
PRICE_EMISSION.l(node,type_emission,type_tec,year)$( SUM(emission$( cat_emission(type_emission,emission) ),
EMISSION_EQUIVALENCE.m(node,emission,type_tec,year) ) ) =
SMAX(emission$( cat_emission(type_emission,emission) ),
EMISSION_EQUIVALENCE.m(node,emission,type_tec,year) / emission_scaling(type_emission,emission) )
/ df_period(year);
PRICE_EMISSION_NEW.l(node,type_emission,type_tec,year)$(
( PRICE_EMISSION_NEW.l(node,type_emission,type_tec,year) = eps ) or
( PRICE_EMISSION_NEW.l(node,type_emission,type_tec,year) = -inf ) ) = 0 ;
PRICE_EMISSION.l(node,type_emission,type_tec,year)$(
( PRICE_EMISSION.l(node,type_emission,type_tec,year) = eps ) or
( PRICE_EMISSION.l(node,type_emission,type_tec,year) = -inf ) ) = 0 ;

%AUX_BOUNDS% AUX_ACT_BOUND_LO(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 ;
Expand Down
10 changes: 1 addition & 9 deletions message_ix/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,8 +407,6 @@ def initialize(cls, scenario):
par("commodity_stock", "n c l y")
par("construction_time", "nl t yv")
par("demand", "n c l y h")
par("df_year", "y")
par("df_period", "y")
par("duration_period", "y")
par("duration_time", "h")
par("dynamic_land_lo", "n s y u")
Expand Down Expand Up @@ -457,7 +455,6 @@ def initialize(cls, scenario):
par("level_cost_activity_soft_up", "nl t ya h")
par("level_cost_new_capacity_soft_lo", "nl t yv")
par("level_cost_new_capacity_soft_up", "nl t yv")
par("levelized_cost", "n t y h")
par("min_utilization_factor", "nl t yv ya")
par("operation_factor", "nl t yv ya")
par("output", "nl t yv ya m nd c l h hd")
Expand Down Expand Up @@ -560,12 +557,7 @@ def initialize(cls, scenario):
var(
"PRICE_EMISSION",
"n type_emission type_tec y",
"Emission price (derived from marginals of EMISSION_BOUND constraint)",
)
var(
"PRICE_EMISSION_NEW",
"n type_emission type_tec y",
"TEMPORARY test for Emission price fix",
"Emission price (derived from marginals of EMISSION_EQUIVALENCE constraint)",
)
var(
"REL",
Expand Down
6 changes: 4 additions & 2 deletions message_ix/tests/test_feature_price_emission.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@

solve_args = {
"equ_list": ["EMISSION_EQUIVALENCE"],
"par_list": ["df_period", "df_year", "levelized_cost"],
"var_list": ["PRICE_EMISSION_NEW"],
# "par_list": ["df_period", "df_year", "levelized_cost"],
# At the moment, it is not possible to retrieve auxilliary parameters that
# are created in GAMS back to ixmp. The default "par_list" is coded in Java
# backened, and specifying a list here does not add/modify the default list.
}


Expand Down

0 comments on commit 41c5dd1

Please sign in to comment.