From 364aafe0dbffe0a8aa4672be9a79b2427c76a5cf Mon Sep 17 00:00:00 2001 From: Unknown Date: Wed, 29 Sep 2021 14:37:16 +0200 Subject: [PATCH 01/47] draft of regional emission pool implementation - added new parameter emission_sink_rate - added new equation EMISSION_POOL with variable EMISS_POOL - possibility to limit size of pools via constraint currently not included - note that I did not run the code, so it has not been tested for correct syntax --- message_ix/model/MESSAGE/data_load.gms | 2 +- message_ix/model/MESSAGE/model_core.gms | 44 +++++++++++++++++++--- message_ix/model/MESSAGE/parameter_def.gms | 3 ++ 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/message_ix/model/MESSAGE/data_load.gms b/message_ix/model/MESSAGE/data_load.gms index f0b0b4f94..351ca97dd 100644 --- a/message_ix/model/MESSAGE/data_load.gms +++ b/message_ix/model/MESSAGE/data_load.gms @@ -51,7 +51,7 @@ addon_conversion, addon_up, addon_lo rating_bin, reliability_factor, peak_load_factor, flexibility_factor renewable_capacity_factor, renewable_potential * emission factors, bounds and taxes on emissions (including mapping sets) -historical_emission, emission_factor, emission_scaling, is_bound_emission, bound_emission, tax_emission, +historical_emission, emission_factor, emission_scaling, is_bound_emission, bound_emission, tax_emission, emission_sink_rate, * historical values of new capacity investment, activity and extraction historical_new_capacity, historical_activity, historical_extraction * parameters for land-use model emulator diff --git a/message_ix/model/MESSAGE/model_core.gms b/message_ix/model/MESSAGE/model_core.gms index 745485a84..60a47a31f 100644 --- a/message_ix/model/MESSAGE/model_core.gms +++ b/message_ix/model/MESSAGE/model_core.gms @@ -118,6 +118,8 @@ Variables REL(relation,node,year_all) auxiliary variable for left-hand side of user-defined relations * change in the content of storage device STORAGE_CHARGE(node,tec,level,commodity,year_all,time) charging of storage in each timestep (negative for discharge) +* regional emission pool + EMISS_POOL(node,type_emission,type_tec,year_all) nodal-regional-global emission pool size ; *** @@ -272,6 +274,7 @@ Equations ACTIVITY_SOFT_CONSTRAINT_LO bound on relaxation of the dynamic constraint on market penetration (lower bound) EMISSION_EQUIVALENCE auxiliary equation to simplify the notation of emissions EMISSION_CONSTRAINT nodal-regional-global constraints on emissions (by category) + EMISSION_POOL nodal-regional-global emission pool with carbon sink rate LAND_CONSTRAINT constraint on total land use (linear combination of land scenarios adds up to 1) DYNAMIC_LAND_SCEN_CONSTRAINT_UP dynamic constraint on land scenario change (upper bound) DYNAMIC_LAND_SCEN_CONSTRAINT_LO dynamic constraint on land scenario change (lower bound) @@ -1579,12 +1582,12 @@ NEW_CAPACITY_CONSTRAINT_UP(node,inv_tec,year)$( map_tec(node,inv_tec,year) * .. math:: * CAP\_NEW\_UP_{n,t,y} \leq \sum_{y-1} CAP\_NEW_{n^L,t,y-1} & \text{if } y \neq 'first\_period' \\ * + \sum_{y-1} historical\_new\_capacity_{n^L,t,y-1} & \text{if } y = 'first\_period' \\ -* \quad \forall \ t \ \in \ T^{INV} +* \quad \forall \ t \ \in \ T^{INV} * *** NEW_CAPACITY_SOFT_CONSTRAINT_UP(node,inv_tec,year)$( soft_new_capacity_up(node,inv_tec,year) ).. CAP_NEW_UP(node,inv_tec,year) =L= - SUM(year2$( seq_period(year2,year) ), + SUM(year2$( seq_period(year2,year) ), CAP_NEW(node,inv_tec,year2)) $ (NOT first_period(year)) + SUM(year_all2$( seq_period(year_all2,year) ), historical_new_capacity(node,inv_tec,year_all2)) $ first_period(year) @@ -1643,14 +1646,14 @@ NEW_CAPACITY_CONSTRAINT_LO(node,inv_tec,year)$( map_tec(node,inv_tec,year) * .. math:: * CAP\_NEW\_LO_{n,t,y} \leq \sum_{y-1} CAP\_NEW_{n^L,t,y-1} & \text{if } y \neq 'first\_period' \\ * + \sum_{y-1} historical\_new\_capacity_{n^L,t,y-1} & \text{if } y = 'first\_period' \\ -* \quad \forall \ t \ \in \ T^{INV} +* \quad \forall \ t \ \in \ T^{INV} * *** NEW_CAPACITY_SOFT_CONSTRAINT_LO(node,inv_tec,year)$( soft_new_capacity_lo(node,inv_tec,year) ).. CAP_NEW_LO(node,inv_tec,year) =L= SUM(year2$( seq_period(year2,year) ), CAP_NEW(node,inv_tec,year2) ) $ (NOT first_period(year)) - + SUM(year_all2$( seq_period(year_all2,year) ), + + SUM(year_all2$( seq_period(year_all2,year) ), historical_new_capacity(node,inv_tec,year_all2) ) $ first_period(year) ; @@ -1711,7 +1714,7 @@ ACTIVITY_CONSTRAINT_UP(node,tec,year,time)$( map_tec_time(node,tec,year,time) * .. math:: * ACT\_UP_{n,t,y,h} \leq \sum_{y^V \leq y,m,y-1} ACT_{n^L,t,y^V,y-1,m,h} & \text{if } y \neq 'first\_period' \\ * + \sum_{m,y-1} historical\_activity_{n^L,t,y-1,m,h} & \text{if } y = 'first\_period' -* +* * *** ACTIVITY_SOFT_CONSTRAINT_UP(node,tec,year,time)$( soft_activity_up(node,tec,year,time) ).. @@ -1864,6 +1867,37 @@ EMISSION_CONSTRAINT(node,type_emission,type_tec,type_year)$is_bound_emission(nod / SUM(year_all2$( cat_year(type_year,year_all2) ), duration_period(year_all2) ) =L= bound_emission(node,type_emission,type_tec,type_year) ; +*** +* emission pool +* ^^^^^^^^^^^^^ +* +* .. _emission_pool: +* +* Equation EMISSION_POOL +* """""""""""""""""""""" +* :math:`EMISS_POOL_{n,\widehat{e},\widehat{t},\widehat{y}}` is the atmospheric pool at node :math:`n` +* for emission type :math:`\widehat{e}` from technology set :math:`\widehat{t}` in year :math:`\widehat{y}`. +* Via :math:`historical_emission` past emissions can be attributed to node :math:`n`, establishing the initial +* conditions of the pools. The parameter :math:`emission_sink_rate` is projecting the sink rate of emissions +* which in general depends on the size of the pool, but is here treated as an exogenous parameter that needs +* to chosen in line with expected results (or adjusted iteratively). +* +*** + +EMISSION_POOL(node,type_emission,type_tec,year).. + EMISS_POOL(node,type_emission,type_tec,year) =E= +* emission pool from previous period + SUM(year_all$( seq_period(year_all,year) ), + EMISS_POOL(node,type_emission,type_tec,year_all) +* emission additions in current period + + SUM(emission$( cat_emission(type_emission,emission) ), + duration_period(year) * emission_scaling(type_emission,emission) * + ( EMISS(node,emission,type_tec,year) + + historical_emission(node,emission,type_tec,year) ) + ) + ) / (1 + emission_sink_rate(node,type_emission,type_tec,year) * duration_period(year)) +; + *----------------------------------------------------------------------------------------------------------------------* *** * .. _section_landuse_emulator: diff --git a/message_ix/model/MESSAGE/parameter_def.gms b/message_ix/model/MESSAGE/parameter_def.gms index ac5ebe8df..d41bae245 100644 --- a/message_ix/model/MESSAGE/parameter_def.gms +++ b/message_ix/model/MESSAGE/parameter_def.gms @@ -588,6 +588,8 @@ Parameters * - ``node`` | ``type_emission`` | ``type_tec`` | ``type_year`` * * - tax_emission * - ``node`` | ``type_emission`` | ``type_tec`` | ``type_year`` +* * - emission_sink_rate +* - ``node`` | ``type_emission`` | ``type_tec`` | ``year`` * * .. [#em_scaling] The parameter ``emission_scaling`` is the scaling factor to harmonize bounds or taxes across types of * emissions. It allows to efficiently aggregate different emissions/pollutants and set bounds or taxes on various categories. @@ -599,6 +601,7 @@ Parameters emission_scaling(type_emission,emission) scaling factor to harmonize bounds or taxes across types bound_emission(node,type_emission,type_tec,type_year) upper bound on emissions tax_emission(node,type_emission,type_tec,type_year) emission tax + emission_sink_rate(node,type_emission,type_tec,year_all) emission sink rate for regional emission pool formulation ; *----------------------------------------------------------------------------------------------------------------------* From b3889c9cc5173cc1ef2a47e5e9c1c41bea32aaf5 Mon Sep 17 00:00:00 2001 From: FRICKO Oliver Date: Thu, 30 Sep 2021 14:59:33 +0200 Subject: [PATCH 02/47] Update emission_pool formulation --- message_ix/model/MESSAGE/data_load.gms | 2 +- message_ix/model/MESSAGE/model_core.gms | 20 ++++++++++---------- message_ix/model/MESSAGE/parameter_def.gms | 3 +++ message_ix/models.py | 6 ++++++ 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/message_ix/model/MESSAGE/data_load.gms b/message_ix/model/MESSAGE/data_load.gms index 351ca97dd..778a357d8 100644 --- a/message_ix/model/MESSAGE/data_load.gms +++ b/message_ix/model/MESSAGE/data_load.gms @@ -51,7 +51,7 @@ addon_conversion, addon_up, addon_lo rating_bin, reliability_factor, peak_load_factor, flexibility_factor renewable_capacity_factor, renewable_potential * emission factors, bounds and taxes on emissions (including mapping sets) -historical_emission, emission_factor, emission_scaling, is_bound_emission, bound_emission, tax_emission, emission_sink_rate, +historical_emission, emission_factor, emission_scaling, is_bound_emission, bound_emission, tax_emission, emission_sink_rate, historical_emission_pool, * historical values of new capacity investment, activity and extraction historical_new_capacity, historical_activity, historical_extraction * parameters for land-use model emulator diff --git a/message_ix/model/MESSAGE/model_core.gms b/message_ix/model/MESSAGE/model_core.gms index 60a47a31f..29bfcaed9 100644 --- a/message_ix/model/MESSAGE/model_core.gms +++ b/message_ix/model/MESSAGE/model_core.gms @@ -1875,26 +1875,26 @@ EMISSION_CONSTRAINT(node,type_emission,type_tec,type_year)$is_bound_emission(nod * * Equation EMISSION_POOL * """""""""""""""""""""" -* :math:`EMISS_POOL_{n,\widehat{e},\widehat{t},\widehat{y}}` is the atmospheric pool at node :math:`n` +* :math:`EMISS\_POOL_{n,\widehat{e},\widehat{t},\widehat{y}}` is the atmospheric pool at node :math:`n` * for emission type :math:`\widehat{e}` from technology set :math:`\widehat{t}` in year :math:`\widehat{y}`. -* Via :math:`historical_emission` past emissions can be attributed to node :math:`n`, establishing the initial -* conditions of the pools. The parameter :math:`emission_sink_rate` is projecting the sink rate of emissions +* Via :math:`historical\_emission` past emissions can be attributed to node :math:`n`, establishing the initial +* conditions of the pools. The parameter :math:`emission\_sink\_rate` is projecting the sink rate of emissions * which in general depends on the size of the pool, but is here treated as an exogenous parameter that needs * to chosen in line with expected results (or adjusted iteratively). * *** -EMISSION_POOL(node,type_emission,type_tec,year).. +EMISSION_POOL(node,type_emission,type_tec,year)$emission_sink_rate(node,type_emission,type_tec,year).. EMISS_POOL(node,type_emission,type_tec,year) =E= -* emission pool from previous period - SUM(year_all$( seq_period(year_all,year) ), - EMISS_POOL(node,type_emission,type_tec,year_all) +* emission pool from previous period if year != firstmodelyear + SUM(year_all2$( seq_period(year_all2,year) ), + EMISS_POOL(node,type_emission,type_tec,year_all2)$(model_horizon(year_all2) AND NOT first_period(year)) * emission additions in current period + SUM(emission$( cat_emission(type_emission,emission) ), duration_period(year) * emission_scaling(type_emission,emission) * - ( EMISS(node,emission,type_tec,year) - + historical_emission(node,emission,type_tec,year) ) - ) + ( EMISS(node,emission,type_tec,year) ) ) +* emission pool from historical period if year == firstmodelyear + + historical_emission_pool(node,type_emission,type_tec,year_all2)$first_period(year) ) / (1 + emission_sink_rate(node,type_emission,type_tec,year) * duration_period(year)) ; diff --git a/message_ix/model/MESSAGE/parameter_def.gms b/message_ix/model/MESSAGE/parameter_def.gms index d41bae245..e8657c8f6 100644 --- a/message_ix/model/MESSAGE/parameter_def.gms +++ b/message_ix/model/MESSAGE/parameter_def.gms @@ -590,6 +590,8 @@ Parameters * - ``node`` | ``type_emission`` | ``type_tec`` | ``type_year`` * * - emission_sink_rate * - ``node`` | ``type_emission`` | ``type_tec`` | ``year`` +* * - historical_emission_pool [#hist]_ +* - ``node`` | ``type_emission`` | ``type_tec`` | ``year`` * * .. [#em_scaling] The parameter ``emission_scaling`` is the scaling factor to harmonize bounds or taxes across types of * emissions. It allows to efficiently aggregate different emissions/pollutants and set bounds or taxes on various categories. @@ -602,6 +604,7 @@ Parameters bound_emission(node,type_emission,type_tec,type_year) upper bound on emissions tax_emission(node,type_emission,type_tec,type_year) emission tax emission_sink_rate(node,type_emission,type_tec,year_all) emission sink rate for regional emission pool formulation + historical_emission_pool(node,type_emission,type_tec,year_all) historical regional emission pool formulation ; *----------------------------------------------------------------------------------------------------------------------* diff --git a/message_ix/models.py b/message_ix/models.py index 5ac698d19..dc4500a7a 100644 --- a/message_ix/models.py +++ b/message_ix/models.py @@ -167,6 +167,9 @@ def item(ix_type, expr): "dynamic_land_up": item("par", "n land_scenario y land_type"), "emission_factor": item("par", "nl t yv ya m e"), "emission_scaling": item("par", "type_emission e"), + "emission_sink_rate": dict( + ix_type="par", idx_sets=["node", "type_emission", "type_tec", "year"] + ), "fix_cost": item("par", "nl t yv ya"), "fixed_activity": item("par", "nl t yv ya m h"), "fixed_capacity": item("par", "nl t yv ya"), @@ -187,6 +190,9 @@ def item(ix_type, expr): "historical_emission": dict( ix_type="par", idx_sets=["node", "type_emission", "type_tec", "type_year"] ), + "historical_emission_pool": dict( + ix_type="par", idx_sets=["node", "type_emission", "type_tec", "year"] + ), "historical_extraction": item("par", "n c g y"), "historical_gdp": dict(ix_type="par", idx_sets=["node", "year"]), "historical_land": item("par", "n land_scenario y"), From 53d3237b83cecd83888eb54ffc6dff8de2f940cb Mon Sep 17 00:00:00 2001 From: FRICKO Oliver Date: Thu, 30 Sep 2021 15:00:53 +0200 Subject: [PATCH 03/47] Add new tutorial draft on emission_pool --- .../westeros/westeros_emission_pools.ipynb | 374 ++++++++++++++++++ 1 file changed, 374 insertions(+) create mode 100644 tutorial/westeros/westeros_emission_pools.ipynb diff --git a/tutorial/westeros/westeros_emission_pools.ipynb b/tutorial/westeros/westeros_emission_pools.ipynb new file mode 100644 index 000000000..4d8e88371 --- /dev/null +++ b/tutorial/westeros/westeros_emission_pools.ipynb @@ -0,0 +1,374 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Westeros Tutorial - Introducing emissions (part1/2): Adding emission bounds\n", + "\n", + "In the first part, the model chose not base the power system on wind power as electricity from wind turbines was more expensive than electricity produced from coal. However, now we introduce emissions to investigate the impact of climate policy. Let's see what happens then.\n", + "\n", + "**Pre-requisites**\n", + "- You have the *MESSAGEix* framework installed and working\n", + "- You have run Westeros baseline scenario (``westeros_baseline.ipynb``) and solved it successfully" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "application/javascript": [ + "IPython.OutputArea.prototype._should_scroll = function(lines) { return false; }" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import pandas as pd\n", + "import ixmp\n", + "import message_ix\n", + "\n", + "from message_ix.util import make_df\n", + "\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "mp = ixmp.Platform()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "model = 'Westeros Electrified'\n", + "\n", + "base = message_ix.Scenario(mp, model=model, scenario='baseline')\n", + "scen = base.clone(model, 'emission_pool_test','introducing an upper bound on emissions',\n", + " keep_solution=False)\n", + "scen.check_out()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "year_df = scen.vintage_and_active_years()\n", + "vintage_years, act_years = year_df['year_vtg'], year_df['year_act']\n", + "model_horizon = scen.set('year')\n", + "country = 'Westeros'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Introducing Emissions" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "# first we introduce the emission of CO2 and the emission category GHG\n", + "scen.add_set('emission', 'CO2')\n", + "scen.add_cat('emission', 'GHG', 'CO2')\n", + "\n", + "# we now add CO2 emissions to the coal powerplant\n", + "base_emission_factor = {\n", + " 'node_loc': country,\n", + " 'year_vtg': vintage_years,\n", + " 'year_act': act_years,\n", + " 'mode': 'standard',\n", + " 'unit': 'tCO2/kWa',\n", + "}\n", + "\n", + "# adding new units to the model library (needed only once)\n", + "mp.add_unit('tCO2/kWa')\n", + "mp.add_unit('MtCO2')\n", + "\n", + "emission_factor = make_df(base_emission_factor, technology= 'coal_ppl', emission= 'CO2', value = 7.4)\n", + "scen.add_par('emission_factor', emission_factor)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Define a Bound on Emissions\n", + "\n", + "The `type_year: cumulative` assigns an upper bound on the *weighted average of emissions* over the entire time horizon." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "scen.add_par('bound_emission', [country, 'GHG', 'all', 'cumulative'],\n", + " value=500., unit='MtCO2')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Initialize parameters" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "new_var = {'EMISS_POOL': ['node', 'type_emission', 'type_tec', 'year']}\n", + "for var, idx in new_var.items():\n", + " if var not in scen.var_list():\n", + " scen.init_var(var, idx)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Add GHG poolsize for historical period 690" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "scen.add_set('type_year', 690)\n", + "scen.add_set('cat_year', pd.DataFrame({'type_year': [690], 'year': 690}))\n", + "df = pd.DataFrame({\n", + " 'node': 'Westeros',\n", + " 'type_emission': 'GHG',\n", + " 'type_tec': 'all',\n", + " 'year': 690,\n", + " 'value': [100000],\n", + " 'unit': 'MtCO2'\n", + "})\n", + "scen.add_par('historical_emission_pool', df)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Add sinkrate for model-periods" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.DataFrame({\n", + " 'node': 'Westeros',\n", + " 'type_emission': 'GHG',\n", + " 'type_tec': 'all',\n", + " 'year': [700, 710, 720],\n", + " 'value': [0.02, 0.01, 0.005],\n", + " 'unit': '???'\n", + "})\n", + "scen.add_par('emission_sink_rate', df)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Time to Solve the Model" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "scen.commit(comment='introducing emissions and setting an upper bound')\n", + "scen.set_as_default()" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "scen.solve(var_list=['EMISS_POOL'])" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "519718.1875" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "scen.var('OBJ')['lvl']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Checking Results" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
nodetype_emissiontype_tecyearlvlmrg
0WesterosGHGall70088299.7382260.0
1WesterosGHGall71086699.7172630.0
2WesterosGHGall72084447.6958370.0
\n", + "
" + ], + "text/plain": [ + " node type_emission type_tec year lvl mrg\n", + "0 Westeros GHG all 700 88299.738226 0.0\n", + "1 Westeros GHG all 710 86699.717263 0.0\n", + "2 Westeros GHG all 720 84447.695837 0.0" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "scen.var('EMISS_POOL')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Close the connection to the database" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "mp.close_db()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 1bd266f45406331cac4730fd61c7bc1b4ec3d092 Mon Sep 17 00:00:00 2001 From: FRICKO Oliver Date: Thu, 30 Sep 2021 15:21:44 +0200 Subject: [PATCH 04/47] Update emission_pool formulation to use is_XX table --- message_ix/model/MESSAGE/data_load.gms | 3 +- message_ix/model/MESSAGE/model_core.gms | 2 +- message_ix/model/MESSAGE/sets_maps_def.gms | 1 + message_ix/models.py | 3 + .../westeros/westeros_emission_pools.ipynb | 151 +++++------------- 5 files changed, 44 insertions(+), 116 deletions(-) diff --git a/message_ix/model/MESSAGE/data_load.gms b/message_ix/model/MESSAGE/data_load.gms index 778a357d8..3b7ac7026 100644 --- a/message_ix/model/MESSAGE/data_load.gms +++ b/message_ix/model/MESSAGE/data_load.gms @@ -51,7 +51,8 @@ addon_conversion, addon_up, addon_lo rating_bin, reliability_factor, peak_load_factor, flexibility_factor renewable_capacity_factor, renewable_potential * emission factors, bounds and taxes on emissions (including mapping sets) -historical_emission, emission_factor, emission_scaling, is_bound_emission, bound_emission, tax_emission, emission_sink_rate, historical_emission_pool, +historical_emission, emission_factor, emission_scaling, is_bound_emission, bound_emission, tax_emission, +emission_sink_rate, is_emission_sink, historical_emission_pool, * historical values of new capacity investment, activity and extraction historical_new_capacity, historical_activity, historical_extraction * parameters for land-use model emulator diff --git a/message_ix/model/MESSAGE/model_core.gms b/message_ix/model/MESSAGE/model_core.gms index 29bfcaed9..e09b7ecdf 100644 --- a/message_ix/model/MESSAGE/model_core.gms +++ b/message_ix/model/MESSAGE/model_core.gms @@ -1884,7 +1884,7 @@ EMISSION_CONSTRAINT(node,type_emission,type_tec,type_year)$is_bound_emission(nod * *** -EMISSION_POOL(node,type_emission,type_tec,year)$emission_sink_rate(node,type_emission,type_tec,year).. +EMISSION_POOL(node,type_emission,type_tec,year)$is_emission_sink(node,type_emission,type_tec,year).. EMISS_POOL(node,type_emission,type_tec,year) =E= * emission pool from previous period if year != firstmodelyear SUM(year_all2$( seq_period(year_all2,year) ), diff --git a/message_ix/model/MESSAGE/sets_maps_def.gms b/message_ix/model/MESSAGE/sets_maps_def.gms index 2195ed6ad..3602fb8aa 100644 --- a/message_ix/model/MESSAGE/sets_maps_def.gms +++ b/message_ix/model/MESSAGE/sets_maps_def.gms @@ -446,6 +446,7 @@ Sets is_dynamic_activity_lo(node,tec,year_all,time) flag whether lower dynamic constraint exists for a technology (activity) is_bound_emission(node,type_emission,type_tec,type_year) flag whether emissions bound exists + is_emission_sink(node,type_emission,type_tec,year_all) flag whether emission sink rate exists for regional emission pool formulation is_dynamic_land_scen_up(node,land_scenario,year_all) flag whether dynamic upper constraint on land-scenario change exists is_dynamic_land_scen_lo(node,land_scenario,year_all) flag whether dynamic lower constraint on land-scenario change exists diff --git a/message_ix/models.py b/message_ix/models.py index dc4500a7a..1dbc07d2e 100644 --- a/message_ix/models.py +++ b/message_ix/models.py @@ -115,6 +115,9 @@ def item(ix_type, expr): "cat_relation": item("set", "type_relation relation"), "cat_tec": item("set", "type_tec t"), "cat_year": item("set", "type_year y"), + "is_emission_sink": dict( + ix_type="set", idx_sets=["node", "type_emission", "type_tec", "year"] + ), "level_renewable": dict(ix_type="set", idx_sets=["level"]), "level_resource": dict(ix_type="set", idx_sets=["level"]), "level_stocks": dict(ix_type="set", idx_sets=["level"]), diff --git a/tutorial/westeros/westeros_emission_pools.ipynb b/tutorial/westeros/westeros_emission_pools.ipynb index 4d8e88371..35f21ab2e 100644 --- a/tutorial/westeros/westeros_emission_pools.ipynb +++ b/tutorial/westeros/westeros_emission_pools.ipynb @@ -15,22 +15,9 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "application/javascript": [ - "IPython.OutputArea.prototype._should_scroll = function(lines) { return false; }" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "import pandas as pd\n", "import ixmp\n", @@ -43,7 +30,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -52,7 +39,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -66,7 +53,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -85,7 +72,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -121,7 +108,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -138,7 +125,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -157,7 +144,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -183,7 +170,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -198,6 +185,26 @@ "scen.add_par('emission_sink_rate', df)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Add is_sinkrate for model-periods" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Adding mapping sets of new parameters\n", + "if not df.empty:\n", + " for i in df.index:\n", + " d = df.loc[i, :].copy().drop(['value', 'unit'])\n", + " scen.add_set('is_emission_sink', d)" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -207,7 +214,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -217,7 +224,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -226,20 +233,9 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "519718.1875" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "scen.var('OBJ')['lvl']" ] @@ -253,82 +249,9 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
nodetype_emissiontype_tecyearlvlmrg
0WesterosGHGall70088299.7382260.0
1WesterosGHGall71086699.7172630.0
2WesterosGHGall72084447.6958370.0
\n", - "
" - ], - "text/plain": [ - " node type_emission type_tec year lvl mrg\n", - "0 Westeros GHG all 700 88299.738226 0.0\n", - "1 Westeros GHG all 710 86699.717263 0.0\n", - "2 Westeros GHG all 720 84447.695837 0.0" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "scen.var('EMISS_POOL')" ] @@ -342,7 +265,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ From 471db69b6fe1ed791bf12f15729e5add7db8c5fd Mon Sep 17 00:00:00 2001 From: FRICKO Oliver Date: Thu, 30 Sep 2021 16:23:02 +0200 Subject: [PATCH 05/47] Add tax_emission_pool to GAMS code and optionally in tutorial --- message_ix/model/MESSAGE/data_load.gms | 2 +- message_ix/model/MESSAGE/model_core.gms | 4 ++++ message_ix/model/MESSAGE/parameter_def.gms | 3 +++ message_ix/models.py | 3 +++ tutorial/westeros/westeros_emission_pools.ipynb | 17 +++++++++++++++++ 5 files changed, 28 insertions(+), 1 deletion(-) diff --git a/message_ix/model/MESSAGE/data_load.gms b/message_ix/model/MESSAGE/data_load.gms index 3b7ac7026..3972aec02 100644 --- a/message_ix/model/MESSAGE/data_load.gms +++ b/message_ix/model/MESSAGE/data_load.gms @@ -52,7 +52,7 @@ rating_bin, reliability_factor, peak_load_factor, flexibility_factor renewable_capacity_factor, renewable_potential * emission factors, bounds and taxes on emissions (including mapping sets) historical_emission, emission_factor, emission_scaling, is_bound_emission, bound_emission, tax_emission, -emission_sink_rate, is_emission_sink, historical_emission_pool, +emission_sink_rate, is_emission_sink, historical_emission_pool, tax_emission_pool, * historical values of new capacity investment, activity and extraction historical_new_capacity, historical_activity, historical_extraction * parameters for land-use model emulator diff --git a/message_ix/model/MESSAGE/model_core.gms b/message_ix/model/MESSAGE/model_core.gms index e09b7ecdf..b3fb7b41e 100644 --- a/message_ix/model/MESSAGE/model_core.gms +++ b/message_ix/model/MESSAGE/model_core.gms @@ -404,6 +404,10 @@ COST_ACCOUNTING_NODAL(node, year).. emission_scaling(type_emission,emission) * tax_emission(node,type_emission,type_tec,type_year) * EMISS(node,emission,type_tec,year) ) +* emission pool taxes (by parent node, type of technology, year and type of emission) + + SUM((type_emission,type_tec)$( tax_emission_pool(node,type_emission,type_tec,year) ), + tax_emission_pool(node,type_emission,type_tec,year) + * EMISS_POOL(node,type_emission,type_tec,year) ) * cost terms from land-use model emulator (only includes valid node-land_scenario-year combinations) + SUM(land_scenario$( land_cost(node,land_scenario,year) ), land_cost(node,land_scenario,year) * LAND(node,land_scenario,year) ) diff --git a/message_ix/model/MESSAGE/parameter_def.gms b/message_ix/model/MESSAGE/parameter_def.gms index e8657c8f6..d24b0857c 100644 --- a/message_ix/model/MESSAGE/parameter_def.gms +++ b/message_ix/model/MESSAGE/parameter_def.gms @@ -592,6 +592,8 @@ Parameters * - ``node`` | ``type_emission`` | ``type_tec`` | ``year`` * * - historical_emission_pool [#hist]_ * - ``node`` | ``type_emission`` | ``type_tec`` | ``year`` +* * - tax_emission_pool +* - ``node`` | ``type_emission`` | ``type_tec`` | ``year`` * * .. [#em_scaling] The parameter ``emission_scaling`` is the scaling factor to harmonize bounds or taxes across types of * emissions. It allows to efficiently aggregate different emissions/pollutants and set bounds or taxes on various categories. @@ -605,6 +607,7 @@ Parameters tax_emission(node,type_emission,type_tec,type_year) emission tax emission_sink_rate(node,type_emission,type_tec,year_all) emission sink rate for regional emission pool formulation historical_emission_pool(node,type_emission,type_tec,year_all) historical regional emission pool formulation + tax_emission_pool(node,type_emission,type_tec,year_all) emission tax ; *----------------------------------------------------------------------------------------------------------------------* diff --git a/message_ix/models.py b/message_ix/models.py index 1dbc07d2e..7d5020ece 100644 --- a/message_ix/models.py +++ b/message_ix/models.py @@ -257,6 +257,9 @@ def item(ix_type, expr): "tax_emission": dict( ix_type="par", idx_sets=["node", "type_emission", "type_tec", "type_year"] ), + "tax_emission_pool": dict( + ix_type="par", idx_sets=["node", "type_emission", "type_tec", "year"] + ), "tax": item("par", "nl type_tec ya"), "technical_lifetime": item("par", "nl t yv"), # Order of sub-annual time steps diff --git a/tutorial/westeros/westeros_emission_pools.ipynb b/tutorial/westeros/westeros_emission_pools.ipynb index 35f21ab2e..cd8414b3e 100644 --- a/tutorial/westeros/westeros_emission_pools.ipynb +++ b/tutorial/westeros/westeros_emission_pools.ipynb @@ -205,6 +205,23 @@ " scen.add_set('is_emission_sink', d)" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.DataFrame({\n", + " 'node': 'Westeros',\n", + " 'type_emission': 'GHG',\n", + " 'type_tec': 'all',\n", + " 'year': [700, 710, 720],\n", + " 'value': [500, 500, 500],\n", + " 'unit': '???'\n", + "})\n", + "#scen.add_par('tax_emission_pool', df)" + ] + }, { "cell_type": "markdown", "metadata": {}, From b3c8f20571e1b15744f10923c0699ed7be45a1ed Mon Sep 17 00:00:00 2001 From: FRICKO Oliver Date: Fri, 1 Oct 2021 10:42:01 +0200 Subject: [PATCH 06/47] Add parameter bound_emission_pool to GAMS code and tutorial --- message_ix/model/MESSAGE/data_load.gms | 2 +- message_ix/model/MESSAGE/model_core.gms | 17 ++++ message_ix/model/MESSAGE/parameter_def.gms | 13 +-- message_ix/model/MESSAGE/sets_maps_def.gms | 1 + message_ix/models.py | 6 ++ .../westeros/westeros_emission_pools.ipynb | 85 +++++++++++++++++-- 6 files changed, 109 insertions(+), 15 deletions(-) diff --git a/message_ix/model/MESSAGE/data_load.gms b/message_ix/model/MESSAGE/data_load.gms index 3972aec02..5741f924c 100644 --- a/message_ix/model/MESSAGE/data_load.gms +++ b/message_ix/model/MESSAGE/data_load.gms @@ -52,7 +52,7 @@ rating_bin, reliability_factor, peak_load_factor, flexibility_factor renewable_capacity_factor, renewable_potential * emission factors, bounds and taxes on emissions (including mapping sets) historical_emission, emission_factor, emission_scaling, is_bound_emission, bound_emission, tax_emission, -emission_sink_rate, is_emission_sink, historical_emission_pool, tax_emission_pool, +emission_sink_rate, is_emission_sink, historical_emission_pool, tax_emission_pool, is_bound_emission_pool, bound_emission_pool, * historical values of new capacity investment, activity and extraction historical_new_capacity, historical_activity, historical_extraction * parameters for land-use model emulator diff --git a/message_ix/model/MESSAGE/model_core.gms b/message_ix/model/MESSAGE/model_core.gms index b3fb7b41e..fe43733ed 100644 --- a/message_ix/model/MESSAGE/model_core.gms +++ b/message_ix/model/MESSAGE/model_core.gms @@ -275,6 +275,7 @@ Equations EMISSION_EQUIVALENCE auxiliary equation to simplify the notation of emissions EMISSION_CONSTRAINT nodal-regional-global constraints on emissions (by category) EMISSION_POOL nodal-regional-global emission pool with carbon sink rate + EMISSION_POOL_CONSTRAINT nodal-regional-global constraints on emission pool (by type) LAND_CONSTRAINT constraint on total land use (linear combination of land scenarios adds up to 1) DYNAMIC_LAND_SCEN_CONSTRAINT_UP dynamic constraint on land scenario change (upper bound) DYNAMIC_LAND_SCEN_CONSTRAINT_LO dynamic constraint on land scenario change (lower bound) @@ -1902,6 +1903,22 @@ EMISSION_POOL(node,type_emission,type_tec,year)$is_emission_sink(node,type_emiss ) / (1 + emission_sink_rate(node,type_emission,type_tec,year) * duration_period(year)) ; +*** +* Bound on emission pool +* ^^^^^^^^^^^^^^^^^^^^^^ +* +* .. _emission_pool_constraint: +* +* Equation EMISSION_POOL_CONSTRAINT +* """"""""""""""""""""""""""""""""" +* This constraint enforces upper bounds on the emission pool. +* +* +*** +EMISSION_POOL_CONSTRAINT(node,type_emission,type_tec,year)$is_bound_emission_pool(node,type_emission,type_tec,year).. + EMISS_POOL(node,type_emission,type_tec,year) + =L= bound_emission_pool(node,type_emission,type_tec,year) ; + *----------------------------------------------------------------------------------------------------------------------* *** * .. _section_landuse_emulator: diff --git a/message_ix/model/MESSAGE/parameter_def.gms b/message_ix/model/MESSAGE/parameter_def.gms index d24b0857c..098564377 100644 --- a/message_ix/model/MESSAGE/parameter_def.gms +++ b/message_ix/model/MESSAGE/parameter_def.gms @@ -594,6 +594,8 @@ Parameters * - ``node`` | ``type_emission`` | ``type_tec`` | ``year`` * * - tax_emission_pool * - ``node`` | ``type_emission`` | ``type_tec`` | ``year`` +* * - bound_emission_pool +* - ``node`` | ``type_emission`` | ``type_tec`` | ``type`` * * .. [#em_scaling] The parameter ``emission_scaling`` is the scaling factor to harmonize bounds or taxes across types of * emissions. It allows to efficiently aggregate different emissions/pollutants and set bounds or taxes on various categories. @@ -601,13 +603,14 @@ Parameters *** Parameters - historical_emission(node,emission,type_tec,year_all) historical emissions by technology type (including land) - emission_scaling(type_emission,emission) scaling factor to harmonize bounds or taxes across types - bound_emission(node,type_emission,type_tec,type_year) upper bound on emissions - tax_emission(node,type_emission,type_tec,type_year) emission tax + historical_emission(node,emission,type_tec,year_all) historical emissions by technology type (including land) + emission_scaling(type_emission,emission) scaling factor to harmonize bounds or taxes across types + bound_emission(node,type_emission,type_tec,type_year) upper bound on emissions + tax_emission(node,type_emission,type_tec,type_year) emission tax emission_sink_rate(node,type_emission,type_tec,year_all) emission sink rate for regional emission pool formulation historical_emission_pool(node,type_emission,type_tec,year_all) historical regional emission pool formulation - tax_emission_pool(node,type_emission,type_tec,year_all) emission tax + tax_emission_pool(node,type_emission,type_tec,year_all) emission tax + bound_emission_pool(node,type_emission,type_tec,year_all) upper bound on emission pool size ; *----------------------------------------------------------------------------------------------------------------------* diff --git a/message_ix/model/MESSAGE/sets_maps_def.gms b/message_ix/model/MESSAGE/sets_maps_def.gms index 3602fb8aa..a091b1f54 100644 --- a/message_ix/model/MESSAGE/sets_maps_def.gms +++ b/message_ix/model/MESSAGE/sets_maps_def.gms @@ -447,6 +447,7 @@ Sets is_bound_emission(node,type_emission,type_tec,type_year) flag whether emissions bound exists is_emission_sink(node,type_emission,type_tec,year_all) flag whether emission sink rate exists for regional emission pool formulation + is_bound_emission_pool(node,type_emission,type_tec,year_all) flag whether emission pool bound exists is_dynamic_land_scen_up(node,land_scenario,year_all) flag whether dynamic upper constraint on land-scenario change exists is_dynamic_land_scen_lo(node,land_scenario,year_all) flag whether dynamic lower constraint on land-scenario change exists diff --git a/message_ix/models.py b/message_ix/models.py index 7d5020ece..ee427d13d 100644 --- a/message_ix/models.py +++ b/message_ix/models.py @@ -115,6 +115,9 @@ def item(ix_type, expr): "cat_relation": item("set", "type_relation relation"), "cat_tec": item("set", "type_tec t"), "cat_year": item("set", "type_year y"), + "is_bound_emission_pool": dict( + ix_type="set", idx_sets=["node", "type_emission", "type_tec", "year"] + ), "is_emission_sink": dict( ix_type="set", idx_sets=["node", "type_emission", "type_tec", "year"] ), @@ -155,6 +158,9 @@ def item(ix_type, expr): "bound_activity_lo": item("par", "nl t ya m h"), "bound_activity_up": item("par", "nl t ya m h"), "bound_emission": item("par", "n type_emission type_tec type_year"), + "bound_emission_pool": dict( + ix_type="par", idx_sets=["node", "type_emission", "type_tec", "year"] + ), "bound_extraction_up": item("par", "n c g y"), "bound_new_capacity_lo": item("par", "nl t yv"), "bound_new_capacity_up": item("par", "nl t yv"), diff --git a/tutorial/westeros/westeros_emission_pools.ipynb b/tutorial/westeros/westeros_emission_pools.ipynb index cd8414b3e..9131a2304 100644 --- a/tutorial/westeros/westeros_emission_pools.ipynb +++ b/tutorial/westeros/westeros_emission_pools.ipynb @@ -205,21 +205,66 @@ " scen.add_set('is_emission_sink', d)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## OPTIONAL: Add `tax_emission_pool`" + ] + }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "df = pd.DataFrame({\n", - " 'node': 'Westeros',\n", - " 'type_emission': 'GHG',\n", - " 'type_tec': 'all',\n", - " 'year': [700, 710, 720],\n", - " 'value': [500, 500, 500],\n", - " 'unit': '???'\n", - "})\n", - "#scen.add_par('tax_emission_pool', df)" + "add_tep = False\n", + "if add_tep:\n", + " df = pd.DataFrame({\n", + " 'node': 'Westeros',\n", + " 'type_emission': 'GHG',\n", + " 'type_tec': 'all',\n", + " 'year': [700, 710, 720],\n", + " 'value': [500, 500, 500],\n", + " 'unit': '???'\n", + " })\n", + " scen.add_par('tax_emission_pool', df) " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## OPTIONAL: Add `bound_emission_pool`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "add_epb = False\n", + "if add_epb:\n", + " df = pd.DataFrame({\n", + " 'node': 'Westeros',\n", + " 'type_emission': 'GHG',\n", + " 'type_tec': 'all',\n", + " 'year': [700, 710, 720],\n", + " 'value': [87000, 86000, 85000],\n", + " 'unit': '???'\n", + " })\n", + " scen.add_par('bound_emission_pool', df)\n", + "\n", + " # Adding mapping sets of new parameters\n", + " if not df.empty:\n", + " for i in df.index:\n", + " d = df.loc[i, :].copy().drop(['value', 'unit'])\n", + " scen.add_set('is_bound_emission_pool', d)\n", + " \n", + " # Remove bound_emission\n", + " df = scen.par('bound_emission')\n", + " scen.remove_par('bound_emission', df)" ] }, { @@ -264,6 +309,28 @@ "## Checking Results" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# WITHOUT any constraints EMISS_POOL should have results:\n", + "# 700 88299.738226\n", + "# 710 86699.717263\n", + "# 720 84447.695837 \n", + " \n", + "# WITH `tax_emission_pool' EMISS_POOL should have results:\n", + "# 700 86874.248590\n", + "# 710 80820.292479\n", + "# 720 76971.707123\n", + "\n", + "# WITH `bound_emission_pool' EMISS_POOL should have results:\n", + "# 700 87000\n", + "# 710 85975.299326\n", + "# 720 85000" + ] + }, { "cell_type": "code", "execution_count": null, From 764409527a455f5ba9878c40f068c565cf495367 Mon Sep 17 00:00:00 2001 From: FRICKO Oliver Date: Tue, 5 Oct 2021 15:22:02 +0200 Subject: [PATCH 07/47] Update index of EMISS_POOL to match EMISS --- message_ix/model/MESSAGE/model_core.gms | 30 +- message_ix/model/MESSAGE/parameter_def.gms | 8 +- message_ix/model/MESSAGE/sets_maps_def.gms | 2 +- message_ix/model/MESSAGE_master.gms | 3 +- message_ix/model/MESSAGE_project.gpr | 2772 +++++++++++++++++ message_ix/models.py | 92 +- .../westeros/westeros_emission_pools.ipynb | 8 +- 7 files changed, 2846 insertions(+), 69 deletions(-) diff --git a/message_ix/model/MESSAGE/model_core.gms b/message_ix/model/MESSAGE/model_core.gms index fe43733ed..b27a8cabd 100644 --- a/message_ix/model/MESSAGE/model_core.gms +++ b/message_ix/model/MESSAGE/model_core.gms @@ -48,6 +48,7 @@ * :math:`ACT\_LO_{n,t,y,h} \in \mathbb{R}_+` Relaxation of lower dynamic constraint on activity [#ACT_BD]_ * :math:`LAND_{n,s,y} \in [0,1]` Relative share of land-use scenario (for land-use model emulator) * :math:`EMISS_{n,e,\widehat{t},y} \in \mathbb{R}` Auxiliary variable for aggregate emissions by technology type +* :math:`EMISS\_POOL_{n,e,\widehat{t},y} \in \mathbb{R}` Auxiliary variable for aggregate emission pool by technology type * :math:`REL_{r,n,y} \in \mathbb{R}` Auxiliary variable for left-hand side of relations (linear constraints) * :math:`COMMODITY\_USE_{n,c,l,y} \in \mathbb{R}` Auxiliary variable for amount of commodity used at specific level * :math:`COMMODITY\_BALANCE_{n,c,l,y,h} \in \mathbb{R}` Auxiliary variable for right-hand side of :ref:`commodity_balance` @@ -119,7 +120,7 @@ Variables * change in the content of storage device STORAGE_CHARGE(node,tec,level,commodity,year_all,time) charging of storage in each timestep (negative for discharge) * regional emission pool - EMISS_POOL(node,type_emission,type_tec,year_all) nodal-regional-global emission pool size + EMISS_POOL(node,emission,type_tec,year_all) nodal-regional-global emission pool size ; *** @@ -406,9 +407,11 @@ COST_ACCOUNTING_NODAL(node, year).. * tax_emission(node,type_emission,type_tec,type_year) * EMISS(node,emission,type_tec,year) ) * emission pool taxes (by parent node, type of technology, year and type of emission) - + SUM((type_emission,type_tec)$( tax_emission_pool(node,type_emission,type_tec,year) ), - tax_emission_pool(node,type_emission,type_tec,year) - * EMISS_POOL(node,type_emission,type_tec,year) ) + + SUM((type_emission,emission,type_tec)$( emission_scaling(type_emission,emission) + AND tax_emission_pool(node,type_emission,type_tec,year) ), + emission_scaling(type_emission,emission) + * tax_emission_pool(node,type_emission,type_tec,year) + * EMISS_POOL(node,emission,type_tec,year) ) * cost terms from land-use model emulator (only includes valid node-land_scenario-year combinations) + SUM(land_scenario$( land_cost(node,land_scenario,year) ), land_cost(node,land_scenario,year) * LAND(node,land_scenario,year) ) @@ -1889,18 +1892,16 @@ EMISSION_CONSTRAINT(node,type_emission,type_tec,type_year)$is_bound_emission(nod * *** -EMISSION_POOL(node,type_emission,type_tec,year)$is_emission_sink(node,type_emission,type_tec,year).. - EMISS_POOL(node,type_emission,type_tec,year) =E= +EMISSION_POOL(node,emission,type_tec,year)$is_emission_sink(node,emission,type_tec,year).. + EMISS_POOL(node,emission,type_tec,year) =E= * emission pool from previous period if year != firstmodelyear SUM(year_all2$( seq_period(year_all2,year) ), - EMISS_POOL(node,type_emission,type_tec,year_all2)$(model_horizon(year_all2) AND NOT first_period(year)) + EMISS_POOL(node,emission,type_tec,year_all2)$(model_horizon(year_all2) AND NOT first_period(year)) * emission additions in current period - + SUM(emission$( cat_emission(type_emission,emission) ), - duration_period(year) * emission_scaling(type_emission,emission) * - ( EMISS(node,emission,type_tec,year) ) ) + + duration_period(year) * EMISS(node,emission,type_tec,year) * emission pool from historical period if year == firstmodelyear - + historical_emission_pool(node,type_emission,type_tec,year_all2)$first_period(year) - ) / (1 + emission_sink_rate(node,type_emission,type_tec,year) * duration_period(year)) + + historical_emission_pool(node,emission,type_tec,year_all2)$first_period(year) + ) / (1 + emission_sink_rate(node,emission,type_tec,year) * duration_period(year)) ; *** @@ -1916,7 +1917,10 @@ EMISSION_POOL(node,type_emission,type_tec,year)$is_emission_sink(node,type_emiss * *** EMISSION_POOL_CONSTRAINT(node,type_emission,type_tec,year)$is_bound_emission_pool(node,type_emission,type_tec,year).. - EMISS_POOL(node,type_emission,type_tec,year) + SUM( (emission)$( cat_emission(type_emission,emission) ), + emission_scaling(type_emission,emission) + * EMISS_POOL(node,emission,type_tec,year) + ) =L= bound_emission_pool(node,type_emission,type_tec,year) ; *----------------------------------------------------------------------------------------------------------------------* diff --git a/message_ix/model/MESSAGE/parameter_def.gms b/message_ix/model/MESSAGE/parameter_def.gms index 098564377..f7fb5f617 100644 --- a/message_ix/model/MESSAGE/parameter_def.gms +++ b/message_ix/model/MESSAGE/parameter_def.gms @@ -589,9 +589,9 @@ Parameters * * - tax_emission * - ``node`` | ``type_emission`` | ``type_tec`` | ``type_year`` * * - emission_sink_rate -* - ``node`` | ``type_emission`` | ``type_tec`` | ``year`` +* - ``node`` | ``emission`` | ``type_tec`` | ``year`` * * - historical_emission_pool [#hist]_ -* - ``node`` | ``type_emission`` | ``type_tec`` | ``year`` +* - ``node`` | ``emission`` | ``type_tec`` | ``year`` * * - tax_emission_pool * - ``node`` | ``type_emission`` | ``type_tec`` | ``year`` * * - bound_emission_pool @@ -607,8 +607,8 @@ Parameters emission_scaling(type_emission,emission) scaling factor to harmonize bounds or taxes across types bound_emission(node,type_emission,type_tec,type_year) upper bound on emissions tax_emission(node,type_emission,type_tec,type_year) emission tax - emission_sink_rate(node,type_emission,type_tec,year_all) emission sink rate for regional emission pool formulation - historical_emission_pool(node,type_emission,type_tec,year_all) historical regional emission pool formulation + emission_sink_rate(node,emission,type_tec,year_all) emission sink rate for regional emission pool formulation + historical_emission_pool(node,emission,type_tec,year_all) historical regional emission pool formulation tax_emission_pool(node,type_emission,type_tec,year_all) emission tax bound_emission_pool(node,type_emission,type_tec,year_all) upper bound on emission pool size ; diff --git a/message_ix/model/MESSAGE/sets_maps_def.gms b/message_ix/model/MESSAGE/sets_maps_def.gms index a091b1f54..f9943a10f 100644 --- a/message_ix/model/MESSAGE/sets_maps_def.gms +++ b/message_ix/model/MESSAGE/sets_maps_def.gms @@ -446,7 +446,7 @@ Sets is_dynamic_activity_lo(node,tec,year_all,time) flag whether lower dynamic constraint exists for a technology (activity) is_bound_emission(node,type_emission,type_tec,type_year) flag whether emissions bound exists - is_emission_sink(node,type_emission,type_tec,year_all) flag whether emission sink rate exists for regional emission pool formulation + is_emission_sink(node,emission,type_tec,year_all) flag whether emission sink rate exists for regional emission pool formulation is_bound_emission_pool(node,type_emission,type_tec,year_all) flag whether emission pool bound exists is_dynamic_land_scen_up(node,land_scenario,year_all) flag whether dynamic upper constraint on land-scenario change exists diff --git a/message_ix/model/MESSAGE_master.gms b/message_ix/model/MESSAGE_master.gms index bd6bb99fe..5b2df9c26 100644 --- a/message_ix/model/MESSAGE_master.gms +++ b/message_ix/model/MESSAGE_master.gms @@ -45,7 +45,8 @@ $ONGLOBAL *----------------------------------------------------------------------------------------------------------------------* ** scenario/case selection - this must match the name of the MsgData_<%%%>.gdx input data file ** -$SETGLOBAL data "" +**$SETGLOBAL data "Westeros_Electrified_emission_pool_test" +$SETGLOBAL data "Westeros_Electrified_baseline" ** MACRO mode * "none": MESSAGEix is run in stand-alone mode diff --git a/message_ix/model/MESSAGE_project.gpr b/message_ix/model/MESSAGE_project.gpr index ca6d47fe9..d961f9017 100644 --- a/message_ix/model/MESSAGE_project.gpr +++ b/message_ix/model/MESSAGE_project.gpr @@ -1,2 +1,2774 @@ [PROJECT] +[GDXDISP: abs_cost_activity_soft_lo Par 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: type_tec_total Alias 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: type_tec_share Alias 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: type_tec_land Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: type_tec Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: type_node Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: type_emission Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: type_addon Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: trade_cost Par 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: TOTAL_CAPACITY_BOUND_UP Equ 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: TOTAL_CAPACITY_BOUND_LO Equ 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: time3 Alias 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: time2 Alias 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: time_order Par 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: time_od Alias 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: time_act Alias 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: time Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: technical_lifetime Par 3] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: tec2 Alias 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: tec Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: tax_emission Par 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: SYSTEM_RELIABILITY_CONSTRAINT Equ 5] +PlaneDim=0 +RowDim=5 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: SYSTEM_FLEXIBILITY_CONSTRAINT Equ 5] +PlaneDim=0 +RowDim=5 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: storage_tec Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: storage_self_discharge Par 6] +PlaneDim=0 +RowDim=6 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: storage_initial Par 6] +PlaneDim=0 +RowDim=6 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: STORAGE_EQUIVALENCE Equ 9] +PlaneDim=0 +RowDim=9 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6,7,8,9,10 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: STORAGE_CHARGE Var 6] +PlaneDim=0 +RowDim=6 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6,7 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: STORAGE_CHANGE Equ 6] +PlaneDim=0 +RowDim=6 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6,7 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: STORAGE_BALANCE_INIT Equ 6] +PlaneDim=0 +RowDim=6 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6,7 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: STORAGE_BALANCE Equ 6] +PlaneDim=0 +RowDim=6 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6,7 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: STORAGE Var 6] +PlaneDim=0 +RowDim=6 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6,7 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: STOCKS_BALANCE Equ 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: STOCK_CHG Var 5] +PlaneDim=0 +RowDim=5 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: STOCK Var 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: status Par 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: soft_new_capacity_up Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: soft_new_capacity_lo Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: soft_activity_up Par 4] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: soft_activity_lo Par 4] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: SLACK_RELATION_BOUND_UP Var 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: SLACK_RELATION_BOUND_LO Var 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: SLACK_LAND_TYPE_UP Var 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: SLACK_LAND_TYPE_LO Var 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: SLACK_LAND_SCEN_UP Var 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: SLACK_LAND_SCEN_LO Var 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: SLACK_COMMODITY_EQUIVALENCE_UP Var 5] +PlaneDim=0 +RowDim=5 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: SLACK_COMMODITY_EQUIVALENCE_LO Var 5] +PlaneDim=0 +RowDim=5 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: SLACK_CAP_TOTAL_BOUND_UP Var 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: SLACK_CAP_TOTAL_BOUND_LO Var 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: SLACK_CAP_NEW_DYNAMIC_UP Var 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: SLACK_CAP_NEW_DYNAMIC_LO Var 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: SLACK_CAP_NEW_BOUND_UP Var 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: SLACK_CAP_NEW_BOUND_LO Var 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: SLACK_ACT_DYNAMIC_UP Var 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: SLACK_ACT_DYNAMIC_LO Var 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: SLACK_ACT_BOUND_UP Var 5] +PlaneDim=0 +RowDim=5 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: SLACK_ACT_BOUND_LO Var 5] +PlaneDim=0 +RowDim=5 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: shares Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: share_mode_up Par 6] +PlaneDim=0 +RowDim=6 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: share_mode_lo Par 6] +PlaneDim=0 +RowDim=6 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: SHARE_CONSTRAINT_MODE_UP Equ 6] +PlaneDim=0 +RowDim=6 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6,7 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: SHARE_CONSTRAINT_MODE_LO Equ 6] +PlaneDim=0 +RowDim=6 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6,7 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: SHARE_CONSTRAINT_COMMODITY_UP Equ 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: SHARE_CONSTRAINT_COMMODITY_LO Equ 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: share_commodity_up Par 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: share_commodity_lo Par 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: seq_period Set 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: SameAs Set 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: resource_volume Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDIFF] +FILE1=C:\Repo\message_ix\message_ix\model\data\MsgData_GENIE_SSP2_v4.1.7_test_EN_NPi2020-DAC-MP-CO2_1_1000f.gdx +FILE2=C:\Repo\message_ix\message_ix\model\data\MsgData_GENIE_SSP2_v4.1.7_test_EN_NPi2020-DAC-MP_1000f.gdx +OUTFL= +EPS=0.0 +RELEPS=0.0 +SETIGN=0 +FIELD=All fields +FIELDONLY=0 +DIFFONLY=0 + +[GDXDISP: bound_new_capacity_lo Par 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: output Par 11] +PlaneDim=0 +RowDim=10 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6,7,8,9,10,11 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: FilesCompared Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: technical_lifetime Par 4] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: ACTIVITY_BOUND_LO Equ 5] +PlaneDim=0 +RowDim=5 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: ACTIVITY_BOUND_UP Equ 5] +PlaneDim=0 +RowDim=5 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: input Par 10] +PlaneDim=0 +RowDim=9 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,5,6,7,8,9,10,4 +Decim=2 +PlaneRownr=-1 + +[GDXDISP: output Par 10] +PlaneDim=0 +RowDim=9 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,5,6,7,8,9,10,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: technology Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: initial_activity_lo Par 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: tax Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: balance_equality Set 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: capacity_factor Par 5] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,5,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: PRICE_EMISSION Var 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: price_MESSAGE Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: PRICE_COMMODITY Var 5] +PlaneDim=0 +RowDim=5 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: EMISS Var 4] +PlaneDim=1 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=5,1,2,3,4 +Decim=3 +PlaneRownr=-1 + +[GDXDISP: type_year Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: cat_year Set 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: year Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: year_all Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: year_all2 Alias 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: bound_emission Par 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: CAP_NEW Var 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: CAP Var 4] +PlaneDim=1 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=5,1,2,3,4 +Decim=0 +PlaneRownr=-1 +PlaneFilter1=Marginal + +[GDXDISP: fix_cost Par 4] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: ACT Var 6] +PlaneDim=1 +RowDim=5 +Squeeze=1 +SqTrail0=0 +Order=7,1,2,3,5,6,4 +Decim=2 +PlaneRownr=-1 + +[GDXDISP: levelized_cost Par 4] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: inv_cost Par 3] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: inv_tec Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: ref_activity Par 5] +PlaneDim=0 +RowDim=5 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: ref_extraction Par 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: ref_new_capacity Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: ref_relation Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: rating Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: is_bound_new_capacity_up Set 3] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: is_bound_activity_up Set 5] +PlaneDim=0 +RowDim=5 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: report_iteration Par 2] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1,2 +Decim=3 +PlaneRownr=-1 + +[GDXDISP: EC Var 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: addon_conversion Par 7] +PlaneDim=0 +RowDim=7 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6,7 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: bound_activity_lo Par 5] +PlaneDim=0 +RowDim=5 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: cat_year Set 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: cat_tec Set 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: capacity_factor Par 6] +PlaneDim=0 +RowDim=6 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: construction_time Par 4] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: demand Par 6] +PlaneDim=0 +RowDim=5 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,5,6,4 +Decim=0 +PlaneRownr=-1 + +[GDXDISP: fix_cost Par 5] +PlaneDim=1 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=5,1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: growth_activity_lo Par 5] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,5,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: growth_activity_up Par 5] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,5,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: growth_new_capacity_up Par 4] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: initial_activity_up Par 5] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,5,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: initial_new_capacity_up Par 4] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: inv_cost Par 4] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,3 +Decim=3 +PlaneRownr=-1 + +[GDXDISP: inv_tec Set 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: is_bound_new_capacity_up Set 4] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: is_dynamic_activity_up Set 5] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,5,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: is_dynamic_new_capacity_up Set 4] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: is_relation_lower Set 4] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: is_relation_upper Set 4] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: level_cost_activity_soft_lo Par 5] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,5,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: level_cost_activity_soft_up Par 5] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,5,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: map_relation Set 4] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: map_tec Set 4] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: map_tec_mode Set 5] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,5,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: map_tec_time Set 5] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,5,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: var_cost Par 7] +PlaneDim=1 +RowDim=6 +Squeeze=1 +SqTrail0=0 +Order=2,1,3,4,5,6,7 +Decim=7 +PlaneRownr=2 +PlaneFilter1=co2_dis + +[GDXDISP: technology Set 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: soft_activity_up Par 5] +PlaneDim=1 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=2,1,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: soft_activity_lo Par 5] +PlaneDim=1 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=2,1,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: relation_activity Par 8] +PlaneDim=3 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,8,5,2,3,4,7,6 +Decim=7 +PlaneRownr=3 +PlaneFilter1=oper_res +PlaneFilter2=ins1 +PlaneFilter3=dac_5_exports + +[GDXDISP: relation Set 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: bound_new_capacity_up Par 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: cat_addon Set 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: type_relation Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: DEMAND Var 5] +PlaneDim=0 +RowDim=5 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: abs_cost_activity_soft_up Par 5] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,5,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: input Par 11] +PlaneDim=1 +RowDim=10 +Squeeze=1 +SqTrail0=0 +Order=11,1,2,3,4,5,6,7,8,9,10 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: bound_activity_up Par 5] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,5,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: bound_new_capacity_lo Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: bound_new_capacity_up Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: bound_total_capacity_lo Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: bound_total_capacity_up Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: bound_extraction_up Par 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: growth_activity_lo Par 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: growth_activity_up Par 4] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: growth_new_capacity_lo Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: growth_new_capacity_up Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: relation_lower Par 3] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: relation_upper Par 3] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: cat_emission Set 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: emission_factor Par 7] +PlaneDim=0 +RowDim=6 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,5,6,7,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: type_emission Set 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: type_tec Set 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: CAPACITY_CONSTRAINT Equ 5] +PlaneDim=0 +RowDim=5 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: var_cost Par 6] +PlaneDim=0 +RowDim=6 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: land_use Par 4] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: level_resource Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: level_cost_activity_soft_lo Par 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: land_cost Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: land_scenario Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: land_input Par 6] +PlaneDim=0 +RowDim=6 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: land_type Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: initial_land_up Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: initial_land_scen_up Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: initial_land_scen_lo Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: initial_land_lo Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: initial_activity_up Par 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: historical_new_capacity Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: historical_land Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: historical_gdp Par 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: historical_extraction Par 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: historical_emission Par 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: historical_activity Par 5] +PlaneDim=0 +RowDim=5 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: growth_land_up Par 3] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,3,2 +Decim=4 +PlaneRownr=-1 + +[GDXDISP: growth_land_scen_up Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: growth_land_scen_lo Par 3] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: growth_land_lo Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: grow Par 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: grade Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: gdp_calibrate Par 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: flexibility_factor Par 9] +PlaneDim=0 +RowDim=9 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6,7,8,9 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: fixed_stock Par 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: fixed_new_capacity Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: fixed_land Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: fixed_extraction Par 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: fixed_capacity Par 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: fixed_activity Par 6] +PlaneDim=0 +RowDim=6 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: esub Par 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: emission_scaling Par 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: emission_factor Par 6] +PlaneDim=0 +RowDim=6 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: emission Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: dynamic_land_up Par 4] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,4,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: dynamic_land_lo Par 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: duration_time Par 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: duration_period Par 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: drate Par 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: depr Par 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: demand_MESSAGE Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: demand Par 5] +PlaneDim=0 +RowDim=5 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: cost_MESSAGE Par 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: construction_time Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: commodity_stock Par 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: commodity Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: cat_tec Set 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: cat_relation Set 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: cat_node Set 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: cat_emission Set 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: aeei Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: addon_up Par 6] +PlaneDim=0 +RowDim=6 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: addon_lo Par 6] +PlaneDim=0 +RowDim=6 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: addon Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: abs_cost_new_capacity_soft_up Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: abs_cost_new_capacity_soft_lo Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: abs_cost_activity_soft_up Par 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: is_dynamic_land_lo Set 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: is_dynamic_land_scen_lo Set 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: is_dynamic_land_scen_up Set 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: is_dynamic_land_up Set 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: is_fixed_land Set 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: land_output Par 6] +PlaneDim=1 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=5,1,2,3,6,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: land_emission Par 4] +PlaneDim=1 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=4,1,2,3 +Decim=7 +PlaneRownr=1 +PlaneFilter1=LU_CO2 + +[GDXDISP: emission_sink_rate Par 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: EMISSION_POOL Equ 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: EMISSION_EQUIVALENCE Equ 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: ACTIVITY_CONSTRAINT_UP Equ 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: ACTIVITY_RATING_TOTAL Equ 7] +PlaneDim=0 +RowDim=7 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6,7,8 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: ACTIVITY_SOFT_CONSTRAINT_LO Equ 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: ACTIVITY_SOFT_CONSTRAINT_UP Equ 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: ADDON_ACTIVITY_LO Equ 5] +PlaneDim=0 +RowDim=5 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: ADDON_ACTIVITY_UP Equ 5] +PlaneDim=0 +RowDim=5 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: all_modes Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: AUX_ACT_BOUND_LO Set 6] +PlaneDim=0 +RowDim=6 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: AUX_ACT_BOUND_UP Set 6] +PlaneDim=0 +RowDim=6 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: beyond_horizon_factor Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: beyond_horizon_lifetime Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: CAP_FIRM Var 5] +PlaneDim=0 +RowDim=5 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: CAP_NEW_LO Var 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: CAP_NEW_UP Var 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: CAPACITY_MAINTENANCE Equ 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: CAPACITY_MAINTENANCE_HIST Equ 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: CAPACITY_MAINTENANCE_NEW Equ 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: ACT_LO Var 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: ACT_RATING Var 8] +PlaneDim=0 +RowDim=8 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6,7,8,9 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: ACT_UP Var 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: ACTIVITY_BOUND_ALL_MODES_LO Equ 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: ACTIVITY_BOUND_ALL_MODES_UP Equ 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: ACTIVITY_BY_RATING Equ 7] +PlaneDim=0 +RowDim=7 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6,7,8 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: ACTIVITY_CONSTRAINT_LO Equ 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: EMISS_POOL Var 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: emission2 Alias 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: EMISSION_CONSTRAINT Equ 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: check Par 0] +PlaneDim=0 +RowDim=0 +Squeeze=1 +SqTrail0=0 +Order= +Decim=7 +PlaneRownr=-1 + +[GDXDISP: COMMODITY_BALANCE_GT Equ 5] +PlaneDim=0 +RowDim=5 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: COMMODITY_BALANCE_LT Equ 5] +PlaneDim=0 +RowDim=5 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: COMMODITY_USE Var 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: COMMODITY_USE_LEVEL Equ 5] +PlaneDim=0 +RowDim=5 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,6 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: commodity2 Alias 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: construction_time_factor Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: COST_ACCOUNTING_NODAL Equ 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: COST_NODAL Var 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: COST_NODAL_NET Var 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: demand_fixed Par 5] +PlaneDim=0 +RowDim=5 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: df_period Par 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: df_year Par 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: duration_period_sum Par 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: duration_time_rel Par 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: DYNAMIC_LAND_SCEN_CONSTRAINT_LO Equ 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: DYNAMIC_LAND_SCEN_CONSTRAINT_UP Equ 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: DYNAMIC_LAND_TYPE_CONSTRAINT_LO Equ 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: DYNAMIC_LAND_TYPE_CONSTRAINT_UP Equ 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: elapsed_years Par 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: end_of_horizon_factor Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: export_cost Par 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: EXT Var 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: year_order Par 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: macro_base_period Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: mode Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: model_horizon Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: EXTRACTION_BOUND_UP Equ 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: EXTRACTION_EQUIVALENCE Equ 3] +PlaneDim=0 +RowDim=3 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: historical Set 1] +PlaneDim=0 +RowDim=1 +Squeeze=1 +SqTrail0=0 +Order=1 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: historical_emission_pool Par 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: GDP Var 2] +PlaneDim=0 +RowDim=2 +Squeeze=1 +SqTrail0=0 +Order=1,2,3 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: is_bound_extraction_up Set 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[RP:SETS_MAPS_DEF] +1= + +[GDXDISP: is_bound_emission Set 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: is_emission_sink Set 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[RP:PARAMETER_DEF] +1= + +[GDXDISP: tax_emission_pool Par 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: bound_emission_pool Par 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[GDXDISP: is_bound_emission_pool Set 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4 +Decim=7 +PlaneRownr=-1 + +[RP:DATA_LOAD] +1= + +[RP:MESSAGE/MODEL_SOLVE] +1= + +[RP:MODEL_CORE] +1= + +[RP:MESSAGE_MASTER] +1= + +[GDXDISP: EMISSION_POOL_CONSTRAINT Equ 4] +PlaneDim=0 +RowDim=4 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5 +Decim=0 +PlaneRownr=-1 + +[GDXDISP: relation_activity Par 7] +PlaneDim=0 +RowDim=6 +Squeeze=1 +SqTrail0=0 +Order=1,2,3,4,5,7,6 +Decim=7 +PlaneRownr=-1 + +[MRUFILES] +1=C:\Repo\message_ix\message_ix\model\data\MsgData_Westeros_Electrified_emission_pool_test_tax.gdx +2=C:\Repo\message_ix\message_ix\model\data\MsgData_ENGAGE_SSP2_v4.1.7_EN_NPi2020_1000f.gdx +3=C:\Repo\message_ix\message_ix\model\data\MsgData_GENIE_SSP2_v4.1.7_test_EN_NPi2020-DAC-MP_1000_step1.gdx +4=C:\Repo\message_ix\message_ix\model\data\MsgData_GENIE_SSP2_v4.1.7_test_EN_NPi2020-DAC-MP-CO2_1_1000f.gdx +5=C:\Repo\message_ix\message_ix\model\data\MsgData_GENIE_SSP2_v4.1.7_test2_EN_NPi2020-DAC-MP_1000f.gdx +6=C:\Repo\message_ix\message_ix\model\data\MsgData_India_Electrification_baseline.gdx +7=C:\Repo\message_ix\message_ix\model\diffile.log +8=C:\Repo\message_ix\message_ix\model\output\MsgOutput_GENIE_SSP2_v4.1.7_test2_EN_NPi2020-DAC-MP_1000f.gdx + +[OPENWINDOW_1] +FILE0=C:\Repo\message_ix\message_ix\model\data\MsgData_GENIE_SSP2_v4.1.7_test_EN_NPi2020-DAC-HP-bio-low_1000f.gdx +FILE1=C:\Repo\message_ix\message_ix\model\data\MsgData_Westeros_Electrified_emission_pool_test.gdx +FILE2=C:\Repo\message_ix\message_ix\model\MESSAGE/model_solve.gms +FILE3=C:\Repo\message_ix\message_ix\model\MESSAGE\data_load.gms +FILE4=C:\Repo\message_ix\message_ix\model\MESSAGE\model_core.gms +FILE5=C:\Repo\message_ix\message_ix\model\MESSAGE\parameter_def.gms +FILE6=C:\Repo\message_ix\message_ix\model\MESSAGE\sets_maps_def.gms +FILE7=C:\Repo\message_ix\message_ix\model\MESSAGE_master.gms +FILE8=C:\Repo\message_ix\message_ix\model\MESSAGE_master.lst +FILE9=C:\Repo\message_ix\message_ix\model\output\MsgOutput_Westeros_Electrified_emission_pool_test.gdx +FILE10=C:\Repo\message_ix\message_ix\model\output\MsgOutput_Westeros_Electrified_emission_pool_test_tax.gdx +FILE11=C:\Repo\message_ix\message_ix\model\data\MsgData_GENIE_SSP2_v4.1.7_test_EN_NPi2020-DAC-HP-bio-low_1000f.gdx +MAXIM=0 +TOP=-5 +LEFT=70 +HEIGHT=806 +WIDTH=1660 diff --git a/message_ix/models.py b/message_ix/models.py index ee427d13d..17eaf5daa 100644 --- a/message_ix/models.py +++ b/message_ix/models.py @@ -115,50 +115,50 @@ def item(ix_type, expr): "cat_relation": item("set", "type_relation relation"), "cat_tec": item("set", "type_tec t"), "cat_year": item("set", "type_year y"), - "is_bound_emission_pool": dict( - ix_type="set", idx_sets=["node", "type_emission", "type_tec", "year"] - ), - "is_emission_sink": dict( - ix_type="set", idx_sets=["node", "type_emission", "type_tec", "year"] - ), - "level_renewable": dict(ix_type="set", idx_sets=["level"]), - "level_resource": dict(ix_type="set", idx_sets=["level"]), - "level_stocks": dict(ix_type="set", idx_sets=["level"]), - "map_node": dict( - ix_type="set", idx_sets=["node", "node"], idx_names=["node_parent", "node"] - ), - "map_shares_commodity_share": item("set", "s ns n type_tec m c l"), - "map_shares_commodity_total": item("set", "s ns n type_tec m c l"), - "map_spatial_hierarchy": dict( - ix_type="set", - idx_sets=["lvl_spatial", "node", "node"], - idx_names=["lvl_spatial", "node", "node_parent"], - ), - "map_tec_addon": dict(ix_type="set", idx_sets=["technology", "type_addon"]), - # Mapping of storage reservoir to charger/discharger - "map_tec_storage": item("set", "n t storage_tec l c"), - "map_temporal_hierarchy": dict( - ix_type="set", - idx_sets=["lvl_temporal", "time", "time"], - idx_names=["lvl_temporal", "time", "time_parent"], - ), - "map_time": dict( - ix_type="set", idx_sets=["time", "time"], idx_names=["time_parent", "time"] - ), - "type_tec_land": dict(ix_type="set", idx_sets=["type_tec"]), - # - # Parameters - "abs_cost_activity_soft_lo": item("par", "nl t ya h"), - "abs_cost_activity_soft_up": item("par", "nl t ya h"), - "abs_cost_new_capacity_soft_lo": item("par", "nl t yv"), - "abs_cost_new_capacity_soft_up": item("par", "nl t yv"), - "addon_conversion": item("par", "n t yv ya m h type_addon"), - "addon_lo": item("par", "n t ya m h type_addon"), - "addon_up": item("par", "n t ya m h type_addon"), - "bound_activity_lo": item("par", "nl t ya m h"), - "bound_activity_up": item("par", "nl t ya m h"), - "bound_emission": item("par", "n type_emission type_tec type_year"), - "bound_emission_pool": dict( + "is_bound_emission_pool": dict( + ix_type="set", idx_sets=["node", "type_emission", "type_tec", "year"] + ), + "is_emission_sink": dict( + ix_type="set", idx_sets=["node", "emission", "type_tec", "year"] + ), + "level_renewable": dict(ix_type="set", idx_sets=["level"]), + "level_resource": dict(ix_type="set", idx_sets=["level"]), + "level_stocks": dict(ix_type="set", idx_sets=["level"]), + "map_node": dict( + ix_type="set", idx_sets=["node", "node"], idx_names=["node_parent", "node"] + ), + "map_shares_commodity_share": item("set", "s ns n type_tec m c l"), + "map_shares_commodity_total": item("set", "s ns n type_tec m c l"), + "map_spatial_hierarchy": dict( + ix_type="set", + idx_sets=["lvl_spatial", "node", "node"], + idx_names=["lvl_spatial", "node", "node_parent"], + ), + "map_tec_addon": dict(ix_type="set", idx_sets=["technology", "type_addon"]), + # Mapping of storage reservoir to charger/discharger + "map_tec_storage": item("set", "n t storage_tec l c"), + "map_temporal_hierarchy": dict( + ix_type="set", + idx_sets=["lvl_temporal", "time", "time"], + idx_names=["lvl_temporal", "time", "time_parent"], + ), + "map_time": dict( + ix_type="set", idx_sets=["time", "time"], idx_names=["time_parent", "time"] + ), + "type_tec_land": dict(ix_type="set", idx_sets=["type_tec"]), + # + # Parameters + "abs_cost_activity_soft_lo": item("par", "nl t ya h"), + "abs_cost_activity_soft_up": item("par", "nl t ya h"), + "abs_cost_new_capacity_soft_lo": item("par", "nl t yv"), + "abs_cost_new_capacity_soft_up": item("par", "nl t yv"), + "addon_conversion": item("par", "n t yv ya m h type_addon"), + "addon_lo": item("par", "n t ya m h type_addon"), + "addon_up": item("par", "n t ya m h type_addon"), + "bound_activity_lo": item("par", "nl t ya m h"), + "bound_activity_up": item("par", "nl t ya m h"), + "bound_emission": item("par", "n type_emission type_tec type_year"), + "bound_emission_pool": dict( ix_type="par", idx_sets=["node", "type_emission", "type_tec", "year"] ), "bound_extraction_up": item("par", "n c g y"), @@ -177,7 +177,7 @@ def item(ix_type, expr): "emission_factor": item("par", "nl t yv ya m e"), "emission_scaling": item("par", "type_emission e"), "emission_sink_rate": dict( - ix_type="par", idx_sets=["node", "type_emission", "type_tec", "year"] + ix_type="par", idx_sets=["node", "emission", "type_tec", "year"] ), "fix_cost": item("par", "nl t yv ya"), "fixed_activity": item("par", "nl t yv ya m h"), @@ -200,7 +200,7 @@ def item(ix_type, expr): ix_type="par", idx_sets=["node", "type_emission", "type_tec", "type_year"] ), "historical_emission_pool": dict( - ix_type="par", idx_sets=["node", "type_emission", "type_tec", "year"] + ix_type="par", idx_sets=["node", "emission", "type_tec", "year"] ), "historical_extraction": item("par", "n c g y"), "historical_gdp": dict(ix_type="par", idx_sets=["node", "year"]), diff --git a/tutorial/westeros/westeros_emission_pools.ipynb b/tutorial/westeros/westeros_emission_pools.ipynb index 9131a2304..1db1536dd 100644 --- a/tutorial/westeros/westeros_emission_pools.ipynb +++ b/tutorial/westeros/westeros_emission_pools.ipynb @@ -129,7 +129,7 @@ "metadata": {}, "outputs": [], "source": [ - "new_var = {'EMISS_POOL': ['node', 'type_emission', 'type_tec', 'year']}\n", + "new_var = {'EMISS_POOL': ['node', 'emission', 'type_tec', 'year']}\n", "for var, idx in new_var.items():\n", " if var not in scen.var_list():\n", " scen.init_var(var, idx)" @@ -152,7 +152,7 @@ "scen.add_set('cat_year', pd.DataFrame({'type_year': [690], 'year': 690}))\n", "df = pd.DataFrame({\n", " 'node': 'Westeros',\n", - " 'type_emission': 'GHG',\n", + " 'emission': 'CO2',\n", " 'type_tec': 'all',\n", " 'year': 690,\n", " 'value': [100000],\n", @@ -176,7 +176,7 @@ "source": [ "df = pd.DataFrame({\n", " 'node': 'Westeros',\n", - " 'type_emission': 'GHG',\n", + " 'emission': 'CO2',\n", " 'type_tec': 'all',\n", " 'year': [700, 710, 720],\n", " 'value': [0.02, 0.01, 0.005],\n", @@ -244,7 +244,7 @@ "metadata": {}, "outputs": [], "source": [ - "add_epb = False\n", + "add_epb = True\n", "if add_epb:\n", " df = pd.DataFrame({\n", " 'node': 'Westeros',\n", From 02ef4d85c0a27271d73c10f26fb88b1b733815a5 Mon Sep 17 00:00:00 2001 From: FRICKO Oliver Date: Fri, 8 Oct 2021 09:57:41 +0200 Subject: [PATCH 08/47] Adjust naming of sets for consistency --- message_ix/model/MESSAGE/data_load.gms | 2 +- message_ix/model/MESSAGE/model_core.gms | 2 +- message_ix/model/MESSAGE/sets_maps_def.gms | 2 +- message_ix/models.py | 90 +++++++++++----------- 4 files changed, 48 insertions(+), 48 deletions(-) diff --git a/message_ix/model/MESSAGE/data_load.gms b/message_ix/model/MESSAGE/data_load.gms index 5741f924c..dd008ae42 100644 --- a/message_ix/model/MESSAGE/data_load.gms +++ b/message_ix/model/MESSAGE/data_load.gms @@ -52,7 +52,7 @@ rating_bin, reliability_factor, peak_load_factor, flexibility_factor renewable_capacity_factor, renewable_potential * emission factors, bounds and taxes on emissions (including mapping sets) historical_emission, emission_factor, emission_scaling, is_bound_emission, bound_emission, tax_emission, -emission_sink_rate, is_emission_sink, historical_emission_pool, tax_emission_pool, is_bound_emission_pool, bound_emission_pool, +emission_sink_rate, is_emission_sink_rate, historical_emission_pool, tax_emission_pool, is_bound_emission_pool, bound_emission_pool, * historical values of new capacity investment, activity and extraction historical_new_capacity, historical_activity, historical_extraction * parameters for land-use model emulator diff --git a/message_ix/model/MESSAGE/model_core.gms b/message_ix/model/MESSAGE/model_core.gms index b27a8cabd..30e19e898 100644 --- a/message_ix/model/MESSAGE/model_core.gms +++ b/message_ix/model/MESSAGE/model_core.gms @@ -1892,7 +1892,7 @@ EMISSION_CONSTRAINT(node,type_emission,type_tec,type_year)$is_bound_emission(nod * *** -EMISSION_POOL(node,emission,type_tec,year)$is_emission_sink(node,emission,type_tec,year).. +EMISSION_POOL(node,emission,type_tec,year)$is_emission_sink_rate(node,emission,type_tec,year).. EMISS_POOL(node,emission,type_tec,year) =E= * emission pool from previous period if year != firstmodelyear SUM(year_all2$( seq_period(year_all2,year) ), diff --git a/message_ix/model/MESSAGE/sets_maps_def.gms b/message_ix/model/MESSAGE/sets_maps_def.gms index f9943a10f..4085ea7c2 100644 --- a/message_ix/model/MESSAGE/sets_maps_def.gms +++ b/message_ix/model/MESSAGE/sets_maps_def.gms @@ -446,7 +446,7 @@ Sets is_dynamic_activity_lo(node,tec,year_all,time) flag whether lower dynamic constraint exists for a technology (activity) is_bound_emission(node,type_emission,type_tec,type_year) flag whether emissions bound exists - is_emission_sink(node,emission,type_tec,year_all) flag whether emission sink rate exists for regional emission pool formulation + is_emission_sink_rate(node,emission,type_tec,year_all) flag whether emission sink rate exists for regional emission pool formulation is_bound_emission_pool(node,type_emission,type_tec,year_all) flag whether emission pool bound exists is_dynamic_land_scen_up(node,land_scenario,year_all) flag whether dynamic upper constraint on land-scenario change exists diff --git a/message_ix/models.py b/message_ix/models.py index 17eaf5daa..21329f488 100644 --- a/message_ix/models.py +++ b/message_ix/models.py @@ -11,7 +11,7 @@ #: Solver options used by :meth:`message_ix.Scenario.solve`. DEFAULT_CPLEX_OPTIONS = { "advind": 0, - "lpmethod": 2, + "lpmethod": 4, "threads": 4, "epopt": 1e-6, } @@ -115,50 +115,50 @@ def item(ix_type, expr): "cat_relation": item("set", "type_relation relation"), "cat_tec": item("set", "type_tec t"), "cat_year": item("set", "type_year y"), - "is_bound_emission_pool": dict( - ix_type="set", idx_sets=["node", "type_emission", "type_tec", "year"] - ), - "is_emission_sink": dict( - ix_type="set", idx_sets=["node", "emission", "type_tec", "year"] - ), - "level_renewable": dict(ix_type="set", idx_sets=["level"]), - "level_resource": dict(ix_type="set", idx_sets=["level"]), - "level_stocks": dict(ix_type="set", idx_sets=["level"]), - "map_node": dict( - ix_type="set", idx_sets=["node", "node"], idx_names=["node_parent", "node"] - ), - "map_shares_commodity_share": item("set", "s ns n type_tec m c l"), - "map_shares_commodity_total": item("set", "s ns n type_tec m c l"), - "map_spatial_hierarchy": dict( - ix_type="set", - idx_sets=["lvl_spatial", "node", "node"], - idx_names=["lvl_spatial", "node", "node_parent"], - ), - "map_tec_addon": dict(ix_type="set", idx_sets=["technology", "type_addon"]), - # Mapping of storage reservoir to charger/discharger - "map_tec_storage": item("set", "n t storage_tec l c"), - "map_temporal_hierarchy": dict( - ix_type="set", - idx_sets=["lvl_temporal", "time", "time"], - idx_names=["lvl_temporal", "time", "time_parent"], - ), - "map_time": dict( - ix_type="set", idx_sets=["time", "time"], idx_names=["time_parent", "time"] - ), - "type_tec_land": dict(ix_type="set", idx_sets=["type_tec"]), - # - # Parameters - "abs_cost_activity_soft_lo": item("par", "nl t ya h"), - "abs_cost_activity_soft_up": item("par", "nl t ya h"), - "abs_cost_new_capacity_soft_lo": item("par", "nl t yv"), - "abs_cost_new_capacity_soft_up": item("par", "nl t yv"), - "addon_conversion": item("par", "n t yv ya m h type_addon"), - "addon_lo": item("par", "n t ya m h type_addon"), - "addon_up": item("par", "n t ya m h type_addon"), - "bound_activity_lo": item("par", "nl t ya m h"), - "bound_activity_up": item("par", "nl t ya m h"), - "bound_emission": item("par", "n type_emission type_tec type_year"), - "bound_emission_pool": dict( + "is_bound_emission_pool": dict( + ix_type="set", idx_sets=["node", "type_emission", "type_tec", "year"] + ), + "is_emission_sink_rate": dict( + ix_type="set", idx_sets=["node", "emission", "type_tec", "year"] + ), + "level_renewable": dict(ix_type="set", idx_sets=["level"]), + "level_resource": dict(ix_type="set", idx_sets=["level"]), + "level_stocks": dict(ix_type="set", idx_sets=["level"]), + "map_node": dict( + ix_type="set", idx_sets=["node", "node"], idx_names=["node_parent", "node"] + ), + "map_shares_commodity_share": item("set", "s ns n type_tec m c l"), + "map_shares_commodity_total": item("set", "s ns n type_tec m c l"), + "map_spatial_hierarchy": dict( + ix_type="set", + idx_sets=["lvl_spatial", "node", "node"], + idx_names=["lvl_spatial", "node", "node_parent"], + ), + "map_tec_addon": dict(ix_type="set", idx_sets=["technology", "type_addon"]), + # Mapping of storage reservoir to charger/discharger + "map_tec_storage": item("set", "n t storage_tec l c"), + "map_temporal_hierarchy": dict( + ix_type="set", + idx_sets=["lvl_temporal", "time", "time"], + idx_names=["lvl_temporal", "time", "time_parent"], + ), + "map_time": dict( + ix_type="set", idx_sets=["time", "time"], idx_names=["time_parent", "time"] + ), + "type_tec_land": dict(ix_type="set", idx_sets=["type_tec"]), + # + # Parameters + "abs_cost_activity_soft_lo": item("par", "nl t ya h"), + "abs_cost_activity_soft_up": item("par", "nl t ya h"), + "abs_cost_new_capacity_soft_lo": item("par", "nl t yv"), + "abs_cost_new_capacity_soft_up": item("par", "nl t yv"), + "addon_conversion": item("par", "n t yv ya m h type_addon"), + "addon_lo": item("par", "n t ya m h type_addon"), + "addon_up": item("par", "n t ya m h type_addon"), + "bound_activity_lo": item("par", "nl t ya m h"), + "bound_activity_up": item("par", "nl t ya m h"), + "bound_emission": item("par", "n type_emission type_tec type_year"), + "bound_emission_pool": dict( ix_type="par", idx_sets=["node", "type_emission", "type_tec", "year"] ), "bound_extraction_up": item("par", "n c g y"), From ab7442f7b762377901e43b16d7f83ce01c18b8ce Mon Sep 17 00:00:00 2001 From: FRICKO Oliver Date: Fri, 8 Oct 2021 09:58:19 +0200 Subject: [PATCH 09/47] Extend tutorial to test 'World' tax --- .../westeros/westeros_emission_pools.ipynb | 58 ++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/tutorial/westeros/westeros_emission_pools.ipynb b/tutorial/westeros/westeros_emission_pools.ipynb index 1db1536dd..19f6f1c64 100644 --- a/tutorial/westeros/westeros_emission_pools.ipynb +++ b/tutorial/westeros/westeros_emission_pools.ipynb @@ -129,6 +129,21 @@ "metadata": {}, "outputs": [], "source": [ + "new_par = {\"historical_emission_pool\": ['node', 'emission', 'type_tec', 'year'],\n", + " \"emission_sink_rate\": ['node', 'emission', 'type_tec', 'year'],\n", + " \"bound_emission_pool\": [\"node\", \"type_emission\", \"type_tec\", \"year\"],\n", + " \"tax_emission_pool\": [\"node\", \"type_emission\", \"type_tec\", \"year\"]}\n", + "for par, idx in new_par.items():\n", + " if par not in scen.par_list():\n", + " scen.init_par(par, idx)\n", + "\n", + "new_set = {\n", + " \"is_bound_emission_pool\": [\"node\", \"type_emission\", \"type_tec\", \"year\"],\n", + " \"is_emission_sink_rate\": ['node', 'emission', 'type_tec', 'year']}\n", + "for sets, idx in new_set.items():\n", + " if sets not in scen.set_list():\n", + " scen.init_set(sets, idx)\n", + "\n", "new_var = {'EMISS_POOL': ['node', 'emission', 'type_tec', 'year']}\n", "for var, idx in new_var.items():\n", " if var not in scen.var_list():\n", @@ -202,7 +217,7 @@ "if not df.empty:\n", " for i in df.index:\n", " d = df.loc[i, :].copy().drop(['value', 'unit'])\n", - " scen.add_set('is_emission_sink', d)" + " scen.add_set('is_emission_sink_rate', d)" ] }, { @@ -231,6 +246,45 @@ " scen.add_par('tax_emission_pool', df) " ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## OPTIONAL: Add `tax_emission_pool` for node `World`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "add_tep_wrld = False\n", + "if add_tep_wrld: \n", + " scen.add_set('type_emission', 'CO2')\n", + " scen.add_cat('emission', 'CO2', 'CO2')\n", + " \n", + " for par in ['emission_sink_rate', 'historical_emission_pool']:\n", + " df = scen.par(par)\n", + " df[\"node\"] = 'World'\n", + " scen.add_par(par, df)\n", + " \n", + " for s in ['is_emission_sink_rate']:\n", + " df = scen.set(s)\n", + " df[\"node\"] = 'World'\n", + " scen.add_set(s, df) \n", + " \n", + " df = pd.DataFrame({\n", + " 'node': 'World',\n", + " 'type_emission': 'CO2',\n", + " 'type_tec': 'all',\n", + " 'year': [700, 710, 720],\n", + " 'value': [500, 500, 500],\n", + " 'unit': '???'\n", + " })\n", + " scen.add_par('tax_emission_pool', df) " + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -244,7 +298,7 @@ "metadata": {}, "outputs": [], "source": [ - "add_epb = True\n", + "add_epb = False\n", "if add_epb:\n", " df = pd.DataFrame({\n", " 'node': 'Westeros',\n", From 73fd29e28d8ed0629984d3e1c58f19528d4a8388 Mon Sep 17 00:00:00 2001 From: FRICKO Oliver Date: Tue, 12 Oct 2021 15:04:24 +0200 Subject: [PATCH 10/47] Subtract emission pool taxes from COST_NODAL_NET in MACRO --- message_ix/model/MESSAGE-MACRO_run.gms | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/message_ix/model/MESSAGE-MACRO_run.gms b/message_ix/model/MESSAGE-MACRO_run.gms index 2b94011da..81bd873ef 100644 --- a/message_ix/model/MESSAGE-MACRO_run.gms +++ b/message_ix/model/MESSAGE-MACRO_run.gms @@ -232,6 +232,11 @@ COST_NODAL_NET.L(node_macro,year) = AND map_node(node,node_macro) AND cat_year(type_year,year) ), emission_scaling(type_emission,emission) * tax_emission(node,type_emission,type_tec,type_year) * EMISS.L(node_macro,emission,type_tec,year) ) +* subtract emission pool taxes applied at any higher nodal level (via map_node set) + - sum((type_emission,emission,type_tec,node)$( emission_scaling(type_emission,emission) + AND map_node(node,node_macro) AND tax_emission_pool(node,type_emission,type_tec,year) ), + emission_scaling(type_emission,emission) * tax_emission_pool(node,type_emission,type_tec,year) + * EMISS_POOL.L(node_macro,emission,type_tec,year) ) ; GDP.L(node_macro,year) = (I.L(node_macro,year) + C.L(node_macro,year) + EC.L(node_macro,year)) * 1000 ; From 2e4b51786f21cba8832fb0b999271e84c89c20a6 Mon Sep 17 00:00:00 2001 From: FRICKO Oliver Date: Tue, 12 Oct 2021 16:58:46 +0200 Subject: [PATCH 11/47] Start documentation of new GAMS code --- message_ix/model/MESSAGE/model_core.gms | 14 +++++++++++--- message_ix/model/MESSAGE/parameter_def.gms | 6 +++--- message_ix/model/MESSAGE/sets_maps_def.gms | 2 +- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/message_ix/model/MESSAGE/model_core.gms b/message_ix/model/MESSAGE/model_core.gms index 30e19e898..733a6c83a 100644 --- a/message_ix/model/MESSAGE/model_core.gms +++ b/message_ix/model/MESSAGE/model_core.gms @@ -1883,13 +1883,21 @@ EMISSION_CONSTRAINT(node,type_emission,type_tec,type_year)$is_bound_emission(nod * * Equation EMISSION_POOL * """""""""""""""""""""" -* :math:`EMISS\_POOL_{n,\widehat{e},\widehat{t},\widehat{y}}` is the atmospheric pool at node :math:`n` -* for emission type :math:`\widehat{e}` from technology set :math:`\widehat{t}` in year :math:`\widehat{y}`. -* Via :math:`historical\_emission` past emissions can be attributed to node :math:`n`, establishing the initial +* :math:`EMISS\_POOL_{n,e,\widehat{t},y}` is the atmospheric pool at node :math:`n` +* for emission :math:`e` from technology set :math:`\widehat{t}` in year :math:`y`. +* Via :math:`historical\_emission\_pool` past emissions can be attributed to node :math:`n`, establishing the initial * conditions of the pools. The parameter :math:`emission\_sink\_rate` is projecting the sink rate of emissions * which in general depends on the size of the pool, but is here treated as an exogenous parameter that needs * to chosen in line with expected results (or adjusted iteratively). * +* .. math:: +* EMISS\_POOL_{n,e,\widehat{t},y} = +* \frac{EMISS\_POOL_{n,e,\widehat{t},y-1} \text{if } y \neq 'first\_period' \\ +* + duration\_period_{y} \cdot EMISS_{n,e,\widehat{t},y} +* + historical\_emission\_pool_{n,e,\widehat{t},y-1} \text{if } y \eq 'first\_period' +* } +* { 1 + emission\_sink\_rate_{n,e,\widehat{t},y} \cdot EMISS_{n,e,\widehat{t},y}} +* *** EMISSION_POOL(node,emission,type_tec,year)$is_emission_sink_rate(node,emission,type_tec,year).. diff --git a/message_ix/model/MESSAGE/parameter_def.gms b/message_ix/model/MESSAGE/parameter_def.gms index f7fb5f617..798f3c56c 100644 --- a/message_ix/model/MESSAGE/parameter_def.gms +++ b/message_ix/model/MESSAGE/parameter_def.gms @@ -607,9 +607,9 @@ Parameters emission_scaling(type_emission,emission) scaling factor to harmonize bounds or taxes across types bound_emission(node,type_emission,type_tec,type_year) upper bound on emissions tax_emission(node,type_emission,type_tec,type_year) emission tax - emission_sink_rate(node,emission,type_tec,year_all) emission sink rate for regional emission pool formulation - historical_emission_pool(node,emission,type_tec,year_all) historical regional emission pool formulation - tax_emission_pool(node,type_emission,type_tec,year_all) emission tax + emission_sink_rate(node,emission,type_tec,year_all) emission sink rate for regional emission pool formulation + historical_emission_pool(node,emission,type_tec,year_all) historical size of emission pool by technology type + tax_emission_pool(node,type_emission,type_tec,year_all) emission pool tax bound_emission_pool(node,type_emission,type_tec,year_all) upper bound on emission pool size ; diff --git a/message_ix/model/MESSAGE/sets_maps_def.gms b/message_ix/model/MESSAGE/sets_maps_def.gms index 4085ea7c2..ba8f01fc8 100644 --- a/message_ix/model/MESSAGE/sets_maps_def.gms +++ b/message_ix/model/MESSAGE/sets_maps_def.gms @@ -447,7 +447,7 @@ Sets is_bound_emission(node,type_emission,type_tec,type_year) flag whether emissions bound exists is_emission_sink_rate(node,emission,type_tec,year_all) flag whether emission sink rate exists for regional emission pool formulation - is_bound_emission_pool(node,type_emission,type_tec,year_all) flag whether emission pool bound exists + is_bound_emission_pool(node,type_emission,type_tec,year_all) flag whether emission pool bound exists for regional emission pool formulation is_dynamic_land_scen_up(node,land_scenario,year_all) flag whether dynamic upper constraint on land-scenario change exists is_dynamic_land_scen_lo(node,land_scenario,year_all) flag whether dynamic lower constraint on land-scenario change exists From 3a131f091692947292499e25f5f29143e4f7c095 Mon Sep 17 00:00:00 2001 From: FRICKO Oliver Date: Wed, 13 Oct 2021 08:56:17 +0200 Subject: [PATCH 12/47] Update of documentation for new GAMS code --- message_ix/model/MESSAGE/model_core.gms | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/message_ix/model/MESSAGE/model_core.gms b/message_ix/model/MESSAGE/model_core.gms index 733a6c83a..20bceca8b 100644 --- a/message_ix/model/MESSAGE/model_core.gms +++ b/message_ix/model/MESSAGE/model_core.gms @@ -360,6 +360,9 @@ OBJECTIVE.. * & + \sum_{\substack{\widehat{e},\widehat{t} \\ e \in E(\widehat{e})}} * emission\_scaling_{\widehat{e},e} \cdot \ emission\_tax_{n,\widehat{e},\widehat{t},y} * \cdot EMISS_{n,e,\widehat{t},y} \\ +* & + \sum_{\substack{\widehat{e},\widehat{t} \\ e \in E(\widehat{e})}} +* emission\_scaling_{\widehat{e},e} \cdot \ emission\_tax\_pool_{n,\widehat{e},\widehat{t},y} +* \cdot EMISS\_POOL_{n,e,\widehat{t},y} \\ * & + \sum_{s} land\_cost_{n,s,y} \cdot LAND_{n,s,y} \\ * & + \sum_{r} relation\_cost_{r,n,y} \cdot REL_{r,n,y} *** @@ -1892,9 +1895,12 @@ EMISSION_CONSTRAINT(node,type_emission,type_tec,type_year)$is_bound_emission(nod * * .. math:: * EMISS\_POOL_{n,e,\widehat{t},y} = -* \frac{EMISS\_POOL_{n,e,\widehat{t},y-1} \text{if } y \neq 'first\_period' \\ -* + duration\_period_{y} \cdot EMISS_{n,e,\widehat{t},y} -* + historical\_emission\_pool_{n,e,\widehat{t},y-1} \text{if } y \eq 'first\_period' +* \frac{ +* \begin{array}{l} +* EMISS\_POOL_{n,e,\widehat{t},y-1} \text{if } y \neq 'first\_period' \\ +* + duration\_period_{y} \cdot EMISS_{n,e,\widehat{t},y} \\ +* + historical\_emission\_pool_{n,e,\widehat{t},y-1} \text{if } y = 'first\_period' +* \end{array} * } * { 1 + emission\_sink\_rate_{n,e,\widehat{t},y} \cdot EMISS_{n,e,\widehat{t},y}} * @@ -1922,6 +1928,10 @@ EMISSION_POOL(node,emission,type_tec,year)$is_emission_sink_rate(node,emission,t * """"""""""""""""""""""""""""""""" * This constraint enforces upper bounds on the emission pool. * +* .. math:: +* \sum_{e \in E(\widehat{e})} +* emission\_scaling_{\widehat{e},e} \cdot EMISS\_POOL{n,e,\widehat{t},y} +* \leq bound\_emission\_pool_{n,\widehat{e},\widehat{t},y} * *** EMISSION_POOL_CONSTRAINT(node,type_emission,type_tec,year)$is_bound_emission_pool(node,type_emission,type_tec,year).. From 5a69e43d7c997a10f95bdcfccf4b8af4b886fdd5 Mon Sep 17 00:00:00 2001 From: Behnam Date: Wed, 13 Oct 2021 11:26:20 +0200 Subject: [PATCH 13/47] Update model_core for consistency in variable and equation names --- message_ix/model/MESSAGE/model_core.gms | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/message_ix/model/MESSAGE/model_core.gms b/message_ix/model/MESSAGE/model_core.gms index 20bceca8b..e0673e854 100644 --- a/message_ix/model/MESSAGE/model_core.gms +++ b/message_ix/model/MESSAGE/model_core.gms @@ -144,7 +144,8 @@ 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 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(node,type_emission,type_tec,year_all) emission price (derived from marginals of EMISSION_CONSTRAINT) + PRICE_EMISSION_POOL(node,type_emission,type_tec,year_all) price of pooled emissions (derived from marginals of EMISSION_POOL_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 ; @@ -275,7 +276,7 @@ Equations ACTIVITY_SOFT_CONSTRAINT_LO bound on relaxation of the dynamic constraint on market penetration (lower bound) EMISSION_EQUIVALENCE auxiliary equation to simplify the notation of emissions EMISSION_CONSTRAINT nodal-regional-global constraints on emissions (by category) - EMISSION_POOL nodal-regional-global emission pool with carbon sink rate + EMISSION_POOL_EQUIVALENCE nodal-regional-global emission pool with carbon sink rate EMISSION_POOL_CONSTRAINT nodal-regional-global constraints on emission pool (by type) LAND_CONSTRAINT constraint on total land use (linear combination of land scenarios adds up to 1) DYNAMIC_LAND_SCEN_CONSTRAINT_UP dynamic constraint on land scenario change (upper bound) @@ -1886,7 +1887,7 @@ EMISSION_CONSTRAINT(node,type_emission,type_tec,type_year)$is_bound_emission(nod * * Equation EMISSION_POOL * """""""""""""""""""""" -* :math:`EMISS\_POOL_{n,e,\widehat{t},y}` is the atmospheric pool at node :math:`n` +* :math:`EMISS\_POOL\_EQUIVALENCE_{n,e,\widehat{t},y}` is the atmospheric pool at node :math:`n` * for emission :math:`e` from technology set :math:`\widehat{t}` in year :math:`y`. * Via :math:`historical\_emission\_pool` past emissions can be attributed to node :math:`n`, establishing the initial * conditions of the pools. The parameter :math:`emission\_sink\_rate` is projecting the sink rate of emissions @@ -1906,7 +1907,7 @@ EMISSION_CONSTRAINT(node,type_emission,type_tec,type_year)$is_bound_emission(nod * *** -EMISSION_POOL(node,emission,type_tec,year)$is_emission_sink_rate(node,emission,type_tec,year).. +EMISSION_POOL_EQUIVALENCE(node,emission,type_tec,year)$is_emission_sink_rate(node,emission,type_tec,year).. EMISS_POOL(node,emission,type_tec,year) =E= * emission pool from previous period if year != firstmodelyear SUM(year_all2$( seq_period(year_all2,year) ), From d66eb601e1f378cca8eb1e3718af7c82ae35512e Mon Sep 17 00:00:00 2001 From: Behnam Date: Wed, 13 Oct 2021 11:27:16 +0200 Subject: [PATCH 14/47] Cleanup tutorial a bit --- tutorial/westeros/westeros_emission_pools.ipynb | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/tutorial/westeros/westeros_emission_pools.ipynb b/tutorial/westeros/westeros_emission_pools.ipynb index 19f6f1c64..392d62f86 100644 --- a/tutorial/westeros/westeros_emission_pools.ipynb +++ b/tutorial/westeros/westeros_emission_pools.ipynb @@ -209,15 +209,13 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "# Adding mapping sets of new parameters\n", "if not df.empty:\n", - " for i in df.index:\n", - " d = df.loc[i, :].copy().drop(['value', 'unit'])\n", - " scen.add_set('is_emission_sink_rate', d)" + " scen.add_set('is_emission_sink_rate', df.drop(['value', 'unit'], axis=1))" ] }, { @@ -312,9 +310,7 @@ "\n", " # Adding mapping sets of new parameters\n", " if not df.empty:\n", - " for i in df.index:\n", - " d = df.loc[i, :].copy().drop(['value', 'unit'])\n", - " scen.add_set('is_bound_emission_pool', d)\n", + " scen.add_set('is_bound_emission_pool', df.drop(['value', 'unit'], axis=1))\n", " \n", " # Remove bound_emission\n", " df = scen.par('bound_emission')\n", From 7dc646642ec73906a16c31fdeb071d941781436a Mon Sep 17 00:00:00 2001 From: Behnam Date: Wed, 13 Oct 2021 11:27:52 +0200 Subject: [PATCH 15/47] Add reporting equation for PRICE_EMISSION_POOL --- message_ix/model/MESSAGE/model_solve.gms | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/message_ix/model/MESSAGE/model_solve.gms b/message_ix/model/MESSAGE/model_solve.gms index a7dae5af0..9fac4b2eb 100644 --- a/message_ix/model/MESSAGE/model_solve.gms +++ b/message_ix/model/MESSAGE/model_solve.gms @@ -47,11 +47,13 @@ EMISSION_CONSTRAINT.m(node,type_emission,type_tec,type_year)$( * SUM(year$( map_first_period(type_year,year) ), duration_period(year) / df_period(year) * df_year(year) ); -* assign auxiliary variables DEMAND, PRICE_COMMODITY and PRICE_EMISSION for integration with MACRO and reporting +* assign auxiliary variables DEMAND and PRICE_COMMODITY for integration with MACRO and reporting DEMAND.l(node,commodity,level,year,time) = demand_fixed(node,commodity,level,year,time) ; 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) ; + +* assign auxiliary variables PRICE_EMISSION and PRICE_EMISSION_POOL for reporting 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.m(node,type_emission,type_tec,type_year) ) @@ -59,6 +61,12 @@ EMISSION_CONSTRAINT.m(node,type_emission,type_tec,type_year)$( PRICE_EMISSION.l(node,type_emission,type_tec,year)$( PRICE_EMISSION.l(node,type_emission,type_tec,year) = - inf ) = 0 ; + PRICE_EMISSION_POOL.l(node,type_emission,type_tec,year) = + - EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year) + / df_year(year) ; + PRICE_EMISSION_POOL.l(node,type_emission,type_tec,year)$( + PRICE_EMISSION_POOL.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 ; %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 From 65bb32fa63f9062fe131cd0804246028744bf24f Mon Sep 17 00:00:00 2001 From: FRICKO Oliver Date: Mon, 18 Oct 2021 16:59:54 +0200 Subject: [PATCH 16/47] Add draft tests for carbon_pool formulation --- message_ix/tests/test_emission_pool.py | 279 +++++++++++++++++++++++++ 1 file changed, 279 insertions(+) create mode 100644 message_ix/tests/test_emission_pool.py diff --git a/message_ix/tests/test_emission_pool.py b/message_ix/tests/test_emission_pool.py new file mode 100644 index 000000000..32ebc2e90 --- /dev/null +++ b/message_ix/tests/test_emission_pool.py @@ -0,0 +1,279 @@ +import pandas as pd +import pandas.testing as pdt + +from message_ix.testing import make_westeros + + +def prep_scenario(s, test_mp): + s.check_out() + + # Initialize parameters + new_par = { + "historical_emission_pool": ["node", "emission", "type_tec", "year"], + "emission_sink_rate": ["node", "emission", "type_tec", "year"], + "bound_emission_pool": ["node", "type_emission", "type_tec", "year"], + "tax_emission_pool": ["node", "type_emission", "type_tec", "year"], + } + for par, idx in new_par.items(): + if par not in s.par_list(): + s.init_par(par, idx) + + # Initialize sets + new_set = { + "is_bound_emission_pool": ["node", "type_emission", "type_tec", "year"], + "is_emission_sink_rate": ["node", "emission", "type_tec", "year"], + } + for sets, idx in new_set.items(): + if sets not in s.set_list(): + s.init_set(sets, idx) + + # Initialize variables + new_var = { + "EMISS_POOL": ["node", "emission", "type_tec", "year"], + "PRICE_EMISSION_POOL": ["node", "type_emission", "type_tec", "year"], + } + for var, idx in new_var.items(): + if var not in s.var_list(): + s.init_var(var, idx) + + # Add emission parameters + s.add_set("emission", "CO2") + s.add_cat("emission", "GHG", "CO2") + test_mp.add_unit("tCO2/kWa") + test_mp.add_unit("MtCO2") + + # Add emission factor + year_df = s.vintage_and_active_years() + emission_factor = { + "node_loc": "Westeros", + "technology": "coal_ppl", + "year_vtg": year_df["year_vtg"], + "year_act": year_df["year_act"], + "mode": "standard", + "unit": "tCO2/kWa", + "emission": "CO2", + "value": 7.4, + } + s.add_par("emission_factor", emission_factor) + + # Add historic emission pool + s.add_set("type_year", 690) + s.add_set("cat_year", pd.DataFrame({"type_year": [690], "year": 690})) + df = pd.DataFrame( + { + "node": "Westeros", + "emission": "CO2", + "type_tec": "all", + "year": 690, + "value": [100000], + "unit": "MtCO2", + } + ) + s.add_par("historical_emission_pool", df) + + df = pd.DataFrame( + { + "node": "Westeros", + "emission": "CO2", + "type_tec": "all", + "year": [700, 710, 720], + "value": [0.02, 0.01, 0.005], + "unit": "???", + } + ) + s.add_par("emission_sink_rate", df) + s.add_set("is_emission_sink_rate", df.drop(["value", "unit"], axis=1)) + + s.commit("prep test sceanrios") + + +def test_add_setup(test_mp): + s = make_westeros(test_mp, quiet=True) + prep_scenario(s, test_mp) + s.solve(var_list=["EMISS_POOL", "PRICE_EMISSION_POOL"]) + + # Ensure that parameter historical_emission_pool + # has been added. + exp = pd.DataFrame( + { + "node": "Westeros", + "emission": "CO2", + "type_tec": "all", + "year": 690, + "value": [100000], + "unit": "MtCO2", + } + ) + + obs = s.par("historical_emission_pool") + + pdt.assert_frame_equal(exp, obs, check_dtype=False) + + # Ensure that parameter emission_sink_rate + # has been added. + exp = pd.DataFrame( + { + "node": "Westeros", + "emission": "CO2", + "type_tec": "all", + "year": [700, 710, 720], + "value": [0.02, 0.01, 0.005], + "unit": "???", + } + ) + + obs = s.par("emission_sink_rate") + + pdt.assert_frame_equal(exp, obs, check_dtype=False) + + # Ensure that set is_emission_sink_rate + # has been added. + exp = exp.drop(["value", "unit"], axis=1) + + obs = s.set("is_emission_sink_rate") + + pdt.assert_frame_equal(exp, obs, check_dtype=False) + + +def test_tax_emission_pool(test_mp): + s = make_westeros(test_mp, quiet=True) + prep_scenario(s, test_mp) + + s.check_out() + df = pd.DataFrame( + { + "node": "Westeros", + "type_emission": "GHG", + "type_tec": "all", + "year": [700, 710, 720], + "value": [500, 500, 500], + "unit": "???", + } + ) + s.add_par("tax_emission_pool", df) + s.commit("tax_emission_pool added") + + s.solve(var_list=["EMISS_POOL", "PRICE_EMISSION_POOL"]) + + exp = pd.DataFrame( + { + "node": "Westeros", + "emission": "CO2", + "type_tec": "all", + "year": [700, 710, 720], + "lvl": [86874.248590, 80820.292479, 76971.707123], + "mrg": 0.0, + } + ) + + obs = s.var("EMISS_POOL") + + pdt.assert_frame_equal(exp, obs, check_dtype=False) + + +def test_tax_emission_pool_world(test_mp): + s = make_westeros(test_mp, quiet=True) + prep_scenario(s, test_mp) + + s.check_out() + s.add_set("type_emission", "CO2") + s.add_cat("emission", "CO2", "CO2") + + for par in ["emission_sink_rate", "historical_emission_pool"]: + df = s.par(par) + df["node"] = "World" + s.add_par(par, df) + + for set in ["is_emission_sink_rate"]: + df = s.set(set) + df["node"] = "World" + s.add_set(set, df) + + df = pd.DataFrame( + { + "node": "World", + "type_emission": "CO2", + "type_tec": "all", + "year": [700, 710, 720], + "value": [500, 500, 500], + "unit": "???", + } + ) + s.add_par("tax_emission_pool", df) + s.commit("tax_emission_pool added") + + s.solve(var_list=["EMISS_POOL", "PRICE_EMISSION_POOL"]) + + exp = pd.DataFrame( + { + "node": 3 * ["World"] + 3 * ["Westeros"], + "emission": "CO2", + "type_tec": "all", + "year": [700, 710, 720, 700, 710, 720], + "lvl": [ + 86874.248590, + 80820.292479, + 76971.707123, + 86874.248590, + 80820.292479, + 76971.707123, + ], + "mrg": 0.0, + } + ) + + obs = s.var("EMISS_POOL") + + pdt.assert_frame_equal(exp, obs, check_dtype=False) + + +def test_bound_emission_pool(test_mp): + s = make_westeros(test_mp, quiet=True) + prep_scenario(s, test_mp) + + s.check_out() + df = pd.DataFrame( + { + "node": "Westeros", + "type_emission": "GHG", + "type_tec": "all", + "year": [700, 710, 720], + "value": [87000, 86000, 85000], + "unit": "???", + } + ) + s.add_par("bound_emission_pool", df) + s.add_set("is_bound_emission_pool", df.drop(["value", "unit"], axis=1)) + s.commit("bound_emission_pool added") + + s.solve(var_list=["EMISS_POOL", "PRICE_EMISSION_POOL"]) + + exp = pd.DataFrame( + { + "node": "Westeros", + "emission": "CO2", + "type_tec": "all", + "year": [700, 710, 720], + "lvl": [87000, 85975.299326, 85000], + "mrg": 0.0, + } + ) + + obs = s.var("EMISS_POOL") + + pdt.assert_frame_equal(exp, obs, check_dtype=False) + + exp = pd.DataFrame( + { + "node": "Westeros", + "type_emission": "GHG", + "type_tec": "all", + "year": [700, 720], + "lvl": [27.397316, 44.070817], + "mrg": 0.0, + } + ) + + obs = s.var("PRICE_EMISSION_POOL") + + pdt.assert_frame_equal(exp, obs, check_dtype=False) From 51ebec2352bfc8d6ca275563007fea9bd8088f5a Mon Sep 17 00:00:00 2001 From: FRICKO Oliver Date: Tue, 19 Oct 2021 10:07:25 +0200 Subject: [PATCH 17/47] Update tests for emission_pool formulation --- message_ix/tests/test_emission_pool.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/message_ix/tests/test_emission_pool.py b/message_ix/tests/test_emission_pool.py index 32ebc2e90..a9ec74856 100644 --- a/message_ix/tests/test_emission_pool.py +++ b/message_ix/tests/test_emission_pool.py @@ -254,7 +254,10 @@ def test_bound_emission_pool(test_mp): "emission": "CO2", "type_tec": "all", "year": [700, 710, 720], - "lvl": [87000, 85975.299326, 85000], + "lvl": [87000, 85476.734072, 85000], + # When changing the capacity factor of wind to 0.36, + # comment in the line below. + # "lvl": [87000, 85975.299326, 85000], "mrg": 0.0, } ) @@ -269,7 +272,10 @@ def test_bound_emission_pool(test_mp): "type_emission": "GHG", "type_tec": "all", "year": [700, 720], - "lvl": [27.397316, 44.070817], + "lvl": [1.8271384, 2.939589], + # When changing the capacity factor of wind to 0.36, + # comment in the line below. + # "lvl": [27.397316, 44.070817], "mrg": 0.0, } ) From 33b481874f37b91fe4384651a3ddafda4ae2dd23 Mon Sep 17 00:00:00 2001 From: FRICKO Oliver Date: Thu, 21 Oct 2021 16:47:51 +0200 Subject: [PATCH 18/47] Adjust cost accounting of emission_pool --- message_ix/model/MESSAGE-MACRO_run.gms | 2 +- message_ix/model/MESSAGE/model_core.gms | 3 ++- message_ix/model/MESSAGE/model_solve.gms | 5 +++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/message_ix/model/MESSAGE-MACRO_run.gms b/message_ix/model/MESSAGE-MACRO_run.gms index 81bd873ef..2b868d0a3 100644 --- a/message_ix/model/MESSAGE-MACRO_run.gms +++ b/message_ix/model/MESSAGE-MACRO_run.gms @@ -236,7 +236,7 @@ COST_NODAL_NET.L(node_macro,year) = - sum((type_emission,emission,type_tec,node)$( emission_scaling(type_emission,emission) AND map_node(node,node_macro) AND tax_emission_pool(node,type_emission,type_tec,year) ), emission_scaling(type_emission,emission) * tax_emission_pool(node,type_emission,type_tec,year) - * EMISS_POOL.L(node_macro,emission,type_tec,year) ) + * EMISS_POOL.L(node_macro,emission,type_tec,year) / duration_period(year)) ; GDP.L(node_macro,year) = (I.L(node_macro,year) + C.L(node_macro,year) + EC.L(node_macro,year)) * 1000 ; diff --git a/message_ix/model/MESSAGE/model_core.gms b/message_ix/model/MESSAGE/model_core.gms index e0673e854..319c1cd51 100644 --- a/message_ix/model/MESSAGE/model_core.gms +++ b/message_ix/model/MESSAGE/model_core.gms @@ -415,7 +415,8 @@ COST_ACCOUNTING_NODAL(node, year).. AND tax_emission_pool(node,type_emission,type_tec,year) ), emission_scaling(type_emission,emission) * tax_emission_pool(node,type_emission,type_tec,year) - * EMISS_POOL(node,emission,type_tec,year) ) + * EMISS_POOL(node,emission,type_tec,year) + / duration_period(year)) * cost terms from land-use model emulator (only includes valid node-land_scenario-year combinations) + SUM(land_scenario$( land_cost(node,land_scenario,year) ), land_cost(node,land_scenario,year) * LAND(node,land_scenario,year) ) diff --git a/message_ix/model/MESSAGE/model_solve.gms b/message_ix/model/MESSAGE/model_solve.gms index 9fac4b2eb..b2e945402 100644 --- a/message_ix/model/MESSAGE/model_solve.gms +++ b/message_ix/model/MESSAGE/model_solve.gms @@ -61,6 +61,11 @@ EMISSION_CONSTRAINT.m(node,type_emission,type_tec,type_year)$( PRICE_EMISSION.l(node,type_emission,type_tec,year)$( PRICE_EMISSION.l(node,type_emission,type_tec,year) = - inf ) = 0 ; +* rescale the dual of the emission constraint to account that the constraint is defined on the average year, not total +EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year)$( + EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year) ) = + EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year) / df_period(year) * df_year(year) ; + PRICE_EMISSION_POOL.l(node,type_emission,type_tec,year) = - EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year) / df_year(year) ; From 48fcc45adee8a4046ce1a9ee33d326b4b5263ad8 Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 21 Oct 2021 17:02:38 +0200 Subject: [PATCH 19/47] Auto stash before merge of "review-carbon-pool" and "volker-krey/carbon_pool" --- message_ix/model/MESSAGE/model_core.gms | 2 +- message_ix/model/MESSAGE/model_solve.gms | 7 +- message_ix/model/MESSAGE_master.gms | 2 +- .../westeros/westeros_emission_pools.ipynb | 155 ++++- .../westeros/westeros_emissions_bounds.ipynb | 133 +++- .../westeros/westeros_emissions_taxes.ipynb | 640 +++++++++++++++++- 6 files changed, 858 insertions(+), 81 deletions(-) diff --git a/message_ix/model/MESSAGE/model_core.gms b/message_ix/model/MESSAGE/model_core.gms index 319c1cd51..69ae2dd3e 100644 --- a/message_ix/model/MESSAGE/model_core.gms +++ b/message_ix/model/MESSAGE/model_core.gms @@ -1932,7 +1932,7 @@ EMISSION_POOL_EQUIVALENCE(node,emission,type_tec,year)$is_emission_sink_rate(nod * * .. math:: * \sum_{e \in E(\widehat{e})} -* emission\_scaling_{\widehat{e},e} \cdot EMISS\_POOL{n,e,\widehat{t},y} +* emission\_scaling_{\widehat{e},e} \cdot EMISS\_POOL{n,e,\widehat{t},y} * \leq bound\_emission\_pool_{n,\widehat{e},\widehat{t},y} * *** diff --git a/message_ix/model/MESSAGE/model_solve.gms b/message_ix/model/MESSAGE/model_solve.gms index b2e945402..10f122b60 100644 --- a/message_ix/model/MESSAGE/model_solve.gms +++ b/message_ix/model/MESSAGE/model_solve.gms @@ -46,6 +46,10 @@ EMISSION_CONSTRAINT.m(node,type_emission,type_tec,type_year)$( / SUM(year$( cat_year(type_year,year) ), duration_period(year) ) * SUM(year$( map_first_period(type_year,year) ), duration_period(year) / df_period(year) * df_year(year) ); +* rescale the dual of the emission constraint to account that the constraint is defined on the average year, not total + EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year)$( + EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year) ) = + EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year) / df_year(year) ; * assign auxiliary variables DEMAND and PRICE_COMMODITY for integration with MACRO and reporting DEMAND.l(node,commodity,level,year,time) = demand_fixed(node,commodity,level,year,time) ; @@ -67,8 +71,7 @@ EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year)$( EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year) / df_period(year) * df_year(year) ; PRICE_EMISSION_POOL.l(node,type_emission,type_tec,year) = - - EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year) - / df_year(year) ; + - EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year) ; PRICE_EMISSION_POOL.l(node,type_emission,type_tec,year)$( PRICE_EMISSION_POOL.l(node,type_emission,type_tec,year) = - inf ) = 0 ; diff --git a/message_ix/model/MESSAGE_master.gms b/message_ix/model/MESSAGE_master.gms index 5b2df9c26..9519c4181 100644 --- a/message_ix/model/MESSAGE_master.gms +++ b/message_ix/model/MESSAGE_master.gms @@ -46,7 +46,7 @@ $ONGLOBAL ** scenario/case selection - this must match the name of the MsgData_<%%%>.gdx input data file ** **$SETGLOBAL data "Westeros_Electrified_emission_pool_test" -$SETGLOBAL data "Westeros_Electrified_baseline" +$SETGLOBAL data "Westeros_Electrified_emission_pool_test" ** MACRO mode * "none": MESSAGEix is run in stand-alone mode diff --git a/tutorial/westeros/westeros_emission_pools.ipynb b/tutorial/westeros/westeros_emission_pools.ipynb index 392d62f86..42710315b 100644 --- a/tutorial/westeros/westeros_emission_pools.ipynb +++ b/tutorial/westeros/westeros_emission_pools.ipynb @@ -15,9 +15,22 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "application/javascript": [ + "IPython.OutputArea.prototype._should_scroll = function(lines) { return false; }" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "import pandas as pd\n", "import ixmp\n", @@ -30,7 +43,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -39,7 +52,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -53,7 +66,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -72,7 +85,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -108,7 +121,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -125,7 +138,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -159,7 +172,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -185,7 +198,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ @@ -209,7 +222,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ @@ -227,18 +240,18 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ - "add_tep = False\n", + "add_tep = True\n", "if add_tep:\n", " df = pd.DataFrame({\n", " 'node': 'Westeros',\n", " 'type_emission': 'GHG',\n", " 'type_tec': 'all',\n", " 'year': [700, 710, 720],\n", - " 'value': [500, 500, 500],\n", + " 'value': [2.92, 0, 1.42],\n", " 'unit': '???'\n", " })\n", " scen.add_par('tax_emission_pool', df) " @@ -253,7 +266,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": {}, "outputs": [], "source": [ @@ -277,7 +290,7 @@ " 'type_emission': 'CO2',\n", " 'type_tec': 'all',\n", " 'year': [700, 710, 720],\n", - " 'value': [500, 500, 500],\n", + " 'value': [2.92, 0, 1.42],\n", " 'unit': '???'\n", " })\n", " scen.add_par('tax_emission_pool', df) " @@ -292,7 +305,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "metadata": {}, "outputs": [], "source": [ @@ -326,7 +339,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "metadata": {}, "outputs": [], "source": [ @@ -336,7 +349,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "metadata": {}, "outputs": [], "source": [ @@ -345,9 +358,20 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "531107.5" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "scen.var('OBJ')['lvl']" ] @@ -361,7 +385,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "metadata": {}, "outputs": [], "source": [ @@ -383,9 +407,82 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
nodeemissiontype_tecyearlvlmrg
0WesterosCO2all70086520.1570640.0
1WesterosCO2all71081191.2481260.0
2WesterosCO2all72077324.9982150.0
\n", + "
" + ], + "text/plain": [ + " node emission type_tec year lvl mrg\n", + "0 Westeros CO2 all 700 86520.157064 0.0\n", + "1 Westeros CO2 all 710 81191.248126 0.0\n", + "2 Westeros CO2 all 720 77324.998215 0.0" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "scen.var('EMISS_POOL')" ] @@ -399,7 +496,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "metadata": {}, "outputs": [], "source": [ @@ -423,7 +520,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.9" + "version": "3.9.2" } }, "nbformat": 4, diff --git a/tutorial/westeros/westeros_emissions_bounds.ipynb b/tutorial/westeros/westeros_emissions_bounds.ipynb index 8e4cce035..1d6a3ce8d 100644 --- a/tutorial/westeros/westeros_emissions_bounds.ipynb +++ b/tutorial/westeros/westeros_emissions_bounds.ipynb @@ -15,9 +15,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "application/javascript": [ + "IPython.OutputArea.prototype._should_scroll = function(lines) { return false; }" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "import pandas as pd\n", "import ixmp\n", @@ -30,7 +43,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -39,7 +52,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -53,7 +66,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -72,7 +85,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -108,7 +121,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -125,7 +138,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -135,7 +148,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -144,9 +157,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "299531.375" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "scen.var('OBJ')['lvl']" ] @@ -160,7 +184,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ @@ -182,9 +206,32 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], "source": [ "rep.set_filters(t=[\"coal_ppl\", \"wind_ppl\"])\n", "rep.get(\"plot activity\")" @@ -201,9 +248,32 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], "source": [ "rep.get(\"plot capacity\")" ] @@ -221,9 +291,32 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], "source": [ "rep.set_filters(t=None, c=[\"light\"])\n", "rep.get(\"plot prices\")" @@ -238,7 +331,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "metadata": {}, "outputs": [], "source": [ @@ -262,7 +355,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.9" + "version": "3.9.2" } }, "nbformat": 4, diff --git a/tutorial/westeros/westeros_emissions_taxes.ipynb b/tutorial/westeros/westeros_emissions_taxes.ipynb index ae563f037..d5e5acfd5 100644 --- a/tutorial/westeros/westeros_emissions_taxes.ipynb +++ b/tutorial/westeros/westeros_emissions_taxes.ipynb @@ -18,9 +18,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "application/javascript": [ + "IPython.OutputArea.prototype._should_scroll = function(lines) { return false; }" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "import pandas as pd\n", "import ixmp\n", @@ -33,7 +46,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -42,7 +55,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -59,7 +72,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -68,9 +81,82 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
nodeemissiontype_tecyearlvlmrg
0WesterosCO2all700536.3717280.0
1WesterosCO2all710678.0347870.0
2WesterosCO2all720285.5934850.0
\n", + "
" + ], + "text/plain": [ + " node emission type_tec year lvl mrg\n", + "0 Westeros CO2 all 700 536.371728 0.0\n", + "1 Westeros CO2 all 710 678.034787 0.0\n", + "2 Westeros CO2 all 720 285.593485 0.0" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "emissions = scen_bd.var('EMISS', {'node': 'Westeros'})\n", "emissions" @@ -78,9 +164,82 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
nodetype_emissiontype_tecyearlvlmrg
0WesterosGHGall7000.1841570.0
1WesterosGHGall7100.2999730.0
2WesterosGHGall7200.4886240.0
\n", + "
" + ], + "text/plain": [ + " node type_emission type_tec year lvl mrg\n", + "0 Westeros GHG all 700 0.184157 0.0\n", + "1 Westeros GHG all 710 0.299973 0.0\n", + "2 Westeros GHG all 720 0.488624 0.0" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "emission_prices = scen_bd.var('PRICE_EMISSION')\n", "emission_prices" @@ -111,7 +270,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -122,9 +281,162 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
node_loctechnologyyear_vtgyear_actmodeemissionvalueunit
0Westeroscoal_ppl690700standardCO27.4tCO2/kWa
1Westeroscoal_ppl690710standardCO27.4tCO2/kWa
2Westeroscoal_ppl690720standardCO27.4tCO2/kWa
3Westeroscoal_ppl700700standardCO27.4tCO2/kWa
4Westeroscoal_ppl700710standardCO27.4tCO2/kWa
5Westeroscoal_ppl700720standardCO27.4tCO2/kWa
6Westeroscoal_ppl710710standardCO27.4tCO2/kWa
7Westeroscoal_ppl710720standardCO27.4tCO2/kWa
8Westeroscoal_ppl720720standardCO27.4tCO2/kWa
\n", + "
" + ], + "text/plain": [ + " node_loc technology year_vtg year_act mode emission value unit\n", + "0 Westeros coal_ppl 690 700 standard CO2 7.4 tCO2/kWa\n", + "1 Westeros coal_ppl 690 710 standard CO2 7.4 tCO2/kWa\n", + "2 Westeros coal_ppl 690 720 standard CO2 7.4 tCO2/kWa\n", + "3 Westeros coal_ppl 700 700 standard CO2 7.4 tCO2/kWa\n", + "4 Westeros coal_ppl 700 710 standard CO2 7.4 tCO2/kWa\n", + "5 Westeros coal_ppl 700 720 standard CO2 7.4 tCO2/kWa\n", + "6 Westeros coal_ppl 710 710 standard CO2 7.4 tCO2/kWa\n", + "7 Westeros coal_ppl 710 720 standard CO2 7.4 tCO2/kWa\n", + "8 Westeros coal_ppl 720 720 standard CO2 7.4 tCO2/kWa" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "scen_bd_by_year.add_set('emission', 'CO2')\n", "scen_bd_by_year.add_cat('emission', 'GHG', 'CO2')\n", @@ -141,9 +453,82 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
nodetype_emissiontype_tectype_yearvalueunit
0WesterosGHGall700536.371728MtCO2
1WesterosGHGall710678.034787MtCO2
2WesterosGHGall720285.593485MtCO2
\n", + "
" + ], + "text/plain": [ + " node type_emission type_tec type_year value unit\n", + "0 Westeros GHG all 700 536.371728 MtCO2\n", + "1 Westeros GHG all 710 678.034787 MtCO2\n", + "2 Westeros GHG all 720 285.593485 MtCO2" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "horizon = [700, 710, 720]\n", "\n", @@ -163,7 +548,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ @@ -172,7 +557,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ @@ -181,9 +566,62 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
nodetype_emissiontype_tecyearlvlmrg
0WesterosGHGall7101.0780250.0
\n", + "
" + ], + "text/plain": [ + " node type_emission type_tec year lvl mrg\n", + "0 Westeros GHG all 710 1.078025 0.0" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "emission_prices_by_year = scen_bd_by_year.var('PRICE_EMISSION')\n", "emission_prices_by_year" @@ -211,7 +649,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "metadata": {}, "outputs": [], "source": [ @@ -222,7 +660,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "metadata": {}, "outputs": [], "source": [ @@ -233,9 +671,82 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
nodetype_emissiontype_tectype_yearvalueunit
0WesterosGHGall7000.184157USD/tCO2
1WesterosGHGall7100.299973USD/tCO2
2WesterosGHGall7200.488624USD/tCO2
\n", + "
" + ], + "text/plain": [ + " node type_emission type_tec type_year value unit\n", + "0 Westeros GHG all 700 0.184157 USD/tCO2\n", + "1 Westeros GHG all 710 0.299973 USD/tCO2\n", + "2 Westeros GHG all 720 0.488624 USD/tCO2" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "scen_tax.add_set('type_year', [700, 710, 720])\n", "\n", @@ -258,7 +769,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "metadata": {}, "outputs": [], "source": [ @@ -267,7 +778,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "metadata": {}, "outputs": [], "source": [ @@ -276,9 +787,82 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
nodeemissiontype_tecyearlvlmrg
0WesterosCO2all700536.3717280.0
1WesterosCO2all710975.3032350.0
2WesterosCO2all7201056.6312820.0
\n", + "
" + ], + "text/plain": [ + " node emission type_tec year lvl mrg\n", + "0 Westeros CO2 all 700 536.371728 0.0\n", + "1 Westeros CO2 all 710 975.303235 0.0\n", + "2 Westeros CO2 all 720 1056.631282 0.0" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "scen_tax.var('EMISS', {'node': 'Westeros'})" ] @@ -301,7 +885,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "metadata": {}, "outputs": [], "source": [ @@ -325,7 +909,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.9" + "version": "3.9.2" } }, "nbformat": 4, From c3682bfbc83872eebb6d5c1475ecf816d5a91f7e Mon Sep 17 00:00:00 2001 From: FRICKO Oliver Date: Fri, 22 Oct 2021 08:45:19 +0200 Subject: [PATCH 20/47] Adjust PRICE_EMISSION_POOL reporting --- message_ix/model/MESSAGE/model_solve.gms | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/message_ix/model/MESSAGE/model_solve.gms b/message_ix/model/MESSAGE/model_solve.gms index 10f122b60..9dd9bec8b 100644 --- a/message_ix/model/MESSAGE/model_solve.gms +++ b/message_ix/model/MESSAGE/model_solve.gms @@ -71,7 +71,8 @@ EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year)$( EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year) / df_period(year) * df_year(year) ; PRICE_EMISSION_POOL.l(node,type_emission,type_tec,year) = - - EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year) ; + - EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year) * duration_period(year) +; PRICE_EMISSION_POOL.l(node,type_emission,type_tec,year)$( PRICE_EMISSION_POOL.l(node,type_emission,type_tec,year) = - inf ) = 0 ; From bc575bb64aeafa4cb5515a43975debf430046362 Mon Sep 17 00:00:00 2001 From: Ben Date: Fri, 22 Oct 2021 10:44:16 +0200 Subject: [PATCH 21/47] Remove the scaling of emission marginals based on df_year --- message_ix/model/MESSAGE/model_solve.gms | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/message_ix/model/MESSAGE/model_solve.gms b/message_ix/model/MESSAGE/model_solve.gms index 9dd9bec8b..41af85237 100644 --- a/message_ix/model/MESSAGE/model_solve.gms +++ b/message_ix/model/MESSAGE/model_solve.gms @@ -68,7 +68,7 @@ EMISSION_CONSTRAINT.m(node,type_emission,type_tec,type_year)$( * rescale the dual of the emission constraint to account that the constraint is defined on the average year, not total EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year)$( EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year) ) = - EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year) / df_period(year) * df_year(year) ; + EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year) / df_period(year) ; PRICE_EMISSION_POOL.l(node,type_emission,type_tec,year) = - EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year) * duration_period(year) From 279d69c3a3fd3b60a2cae6d396ffbb204ffea5a8 Mon Sep 17 00:00:00 2001 From: Ben Date: Fri, 22 Oct 2021 10:44:33 +0200 Subject: [PATCH 22/47] Test tutorial for bound and tax --- .../westeros/westeros_emission_pools.ipynb | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/tutorial/westeros/westeros_emission_pools.ipynb b/tutorial/westeros/westeros_emission_pools.ipynb index 42710315b..dd5f84c03 100644 --- a/tutorial/westeros/westeros_emission_pools.ipynb +++ b/tutorial/westeros/westeros_emission_pools.ipynb @@ -251,10 +251,11 @@ " 'type_emission': 'GHG',\n", " 'type_tec': 'all',\n", " 'year': [700, 710, 720],\n", - " 'value': [2.92, 0, 1.42],\n", + " 'value': [0.0378193, 0, 0.04868423],\n", " 'unit': '???'\n", " })\n", - " scen.add_par('tax_emission_pool', df) " + " scen.add_par('tax_emission_pool', df) \n", + " case = \"tax_emission\"" ] }, { @@ -293,7 +294,8 @@ " 'value': [2.92, 0, 1.42],\n", " 'unit': '???'\n", " })\n", - " scen.add_par('tax_emission_pool', df) " + " scen.add_par('tax_emission_pool', df) \n", + " case = \"tax_emission_world\"" ] }, { @@ -327,7 +329,8 @@ " \n", " # Remove bound_emission\n", " df = scen.par('bound_emission')\n", - " scen.remove_par('bound_emission', df)" + " scen.remove_par('bound_emission', df)\n", + " case = \"bound_emission\"" ] }, { @@ -353,7 +356,7 @@ "metadata": {}, "outputs": [], "source": [ - "scen.solve(var_list=['EMISS_POOL'])" + "scen.solve(var_list=['EMISS_POOL'], case=case)" ] }, { @@ -364,7 +367,7 @@ { "data": { "text/plain": [ - "531107.5" + "303294.28125" ] }, "execution_count": 16, @@ -446,7 +449,7 @@ " CO2\n", " all\n", " 700\n", - " 86520.157064\n", + " 87803.097737\n", " 0.0\n", " \n", " \n", @@ -455,7 +458,7 @@ " CO2\n", " all\n", " 710\n", - " 81191.248126\n", + " 85984.950549\n", " 0.0\n", " \n", " \n", @@ -464,7 +467,7 @@ " CO2\n", " all\n", " 720\n", - " 77324.998215\n", + " 84610.367045\n", " 0.0\n", " \n", " \n", @@ -473,9 +476,9 @@ ], "text/plain": [ " node emission type_tec year lvl mrg\n", - "0 Westeros CO2 all 700 86520.157064 0.0\n", - "1 Westeros CO2 all 710 81191.248126 0.0\n", - "2 Westeros CO2 all 720 77324.998215 0.0" + "0 Westeros CO2 all 700 87803.097737 0.0\n", + "1 Westeros CO2 all 710 85984.950549 0.0\n", + "2 Westeros CO2 all 720 84610.367045 0.0" ] }, "execution_count": 18, From 489032c61c2b7022cce3b700d7cfb8009f0e33eb Mon Sep 17 00:00:00 2001 From: Ben Date: Fri, 22 Oct 2021 14:38:04 +0200 Subject: [PATCH 23/47] Remove extra scaling --- message_ix/model/MESSAGE/model_solve.gms | 5 ----- 1 file changed, 5 deletions(-) diff --git a/message_ix/model/MESSAGE/model_solve.gms b/message_ix/model/MESSAGE/model_solve.gms index 41af85237..5f45eac8b 100644 --- a/message_ix/model/MESSAGE/model_solve.gms +++ b/message_ix/model/MESSAGE/model_solve.gms @@ -46,11 +46,6 @@ EMISSION_CONSTRAINT.m(node,type_emission,type_tec,type_year)$( / SUM(year$( cat_year(type_year,year) ), duration_period(year) ) * SUM(year$( map_first_period(type_year,year) ), duration_period(year) / df_period(year) * df_year(year) ); -* rescale the dual of the emission constraint to account that the constraint is defined on the average year, not total - EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year)$( - EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year) ) = - EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year) / df_year(year) ; - * assign auxiliary variables DEMAND and PRICE_COMMODITY for integration with MACRO and reporting DEMAND.l(node,commodity,level,year,time) = demand_fixed(node,commodity,level,year,time) ; PRICE_COMMODITY.l(node,commodity,level,year,time) = From 51f9a72060cd6ffeada9d801af93d3e895c77261 Mon Sep 17 00:00:00 2001 From: Unknown Date: Mon, 8 Nov 2021 15:12:07 +0100 Subject: [PATCH 24/47] improved documentation of carbon pool implementation in GAMS code --- message_ix/model/MESSAGE/model_core.gms | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/message_ix/model/MESSAGE/model_core.gms b/message_ix/model/MESSAGE/model_core.gms index 69ae2dd3e..5cd376a8e 100644 --- a/message_ix/model/MESSAGE/model_core.gms +++ b/message_ix/model/MESSAGE/model_core.gms @@ -415,7 +415,7 @@ COST_ACCOUNTING_NODAL(node, year).. AND tax_emission_pool(node,type_emission,type_tec,year) ), emission_scaling(type_emission,emission) * tax_emission_pool(node,type_emission,type_tec,year) - * EMISS_POOL(node,emission,type_tec,year) + * EMISS_POOL(node,emission,type_tec,year) / duration_period(year)) * cost terms from land-use model emulator (only includes valid node-land_scenario-year combinations) + SUM(land_scenario$( land_cost(node,land_scenario,year) ), @@ -1881,7 +1881,7 @@ EMISSION_CONSTRAINT(node,type_emission,type_tec,type_year)$is_bound_emission(nod =L= bound_emission(node,type_emission,type_tec,type_year) ; *** -* emission pool +* Emission pool * ^^^^^^^^^^^^^ * * .. _emission_pool: @@ -1897,14 +1897,12 @@ EMISSION_CONSTRAINT(node,type_emission,type_tec,type_year)$is_bound_emission(nod * * .. math:: * EMISS\_POOL_{n,e,\widehat{t},y} = -* \frac{ +* \frac{1}{ 1 + emission\_sink\_rate_{n,e,\widehat{t},y} \cdot EMISS_{n,e,\widehat{t},y}} \cdot \\ * \begin{array}{l} -* EMISS\_POOL_{n,e,\widehat{t},y-1} \text{if } y \neq 'first\_period' \\ +* ( EMISS\_POOL_{n,e,\widehat{t},y-1} \text{, if } y \neq 'first\_period' \\ * + duration\_period_{y} \cdot EMISS_{n,e,\widehat{t},y} \\ -* + historical\_emission\_pool_{n,e,\widehat{t},y-1} \text{if } y = 'first\_period' +* + historical\_emission\_pool_{n,e,\widehat{t},y-1} \text{, if } y = 'first\_period' ) * \end{array} -* } -* { 1 + emission\_sink\_rate_{n,e,\widehat{t},y} \cdot EMISS_{n,e,\widehat{t},y}} * *** @@ -1932,7 +1930,7 @@ EMISSION_POOL_EQUIVALENCE(node,emission,type_tec,year)$is_emission_sink_rate(nod * * .. math:: * \sum_{e \in E(\widehat{e})} -* emission\_scaling_{\widehat{e},e} \cdot EMISS\_POOL{n,e,\widehat{t},y} +* emission\_scaling_{\widehat{e},e} \cdot EMISS\_POOL_{n,e,\widehat{t},y} * \leq bound\_emission\_pool_{n,\widehat{e},\widehat{t},y} * *** From 512cfd478fb69e720303c71031b51640ff710ad0 Mon Sep 17 00:00:00 2001 From: Unknown Date: Mon, 8 Nov 2021 15:20:03 +0100 Subject: [PATCH 25/47] modify carbon pool equations so that pools are always positive --- message_ix/model/MESSAGE/model_core.gms | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/message_ix/model/MESSAGE/model_core.gms b/message_ix/model/MESSAGE/model_core.gms index 5cd376a8e..4643c289d 100644 --- a/message_ix/model/MESSAGE/model_core.gms +++ b/message_ix/model/MESSAGE/model_core.gms @@ -119,6 +119,9 @@ Variables REL(relation,node,year_all) auxiliary variable for left-hand side of user-defined relations * change in the content of storage device STORAGE_CHARGE(node,tec,level,commodity,year_all,time) charging of storage in each timestep (negative for discharge) +; + +Positive variables * regional emission pool EMISS_POOL(node,emission,type_tec,year_all) nodal-regional-global emission pool size ; @@ -1907,7 +1910,7 @@ EMISSION_CONSTRAINT(node,type_emission,type_tec,type_year)$is_bound_emission(nod *** EMISSION_POOL_EQUIVALENCE(node,emission,type_tec,year)$is_emission_sink_rate(node,emission,type_tec,year).. - EMISS_POOL(node,emission,type_tec,year) =E= + EMISS_POOL(node,emission,type_tec,year) =G= * emission pool from previous period if year != firstmodelyear SUM(year_all2$( seq_period(year_all2,year) ), EMISS_POOL(node,emission,type_tec,year_all2)$(model_horizon(year_all2) AND NOT first_period(year)) From e71c389d5b3b111bdea79f132d4991c52f92096f Mon Sep 17 00:00:00 2001 From: Unknown Date: Tue, 9 Nov 2021 06:34:38 +0100 Subject: [PATCH 26/47] corrected error in documentation of emission_pool equation --- message_ix/model/MESSAGE/model_core.gms | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/message_ix/model/MESSAGE/model_core.gms b/message_ix/model/MESSAGE/model_core.gms index 4643c289d..efd5fed1e 100644 --- a/message_ix/model/MESSAGE/model_core.gms +++ b/message_ix/model/MESSAGE/model_core.gms @@ -1900,7 +1900,7 @@ EMISSION_CONSTRAINT(node,type_emission,type_tec,type_year)$is_bound_emission(nod * * .. math:: * EMISS\_POOL_{n,e,\widehat{t},y} = -* \frac{1}{ 1 + emission\_sink\_rate_{n,e,\widehat{t},y} \cdot EMISS_{n,e,\widehat{t},y}} \cdot \\ +* \frac{1}{ 1 + emission\_sink\_rate_{n,e,\widehat{t},y} \cdot duration\_period_{y}} \cdot \\ * \begin{array}{l} * ( EMISS\_POOL_{n,e,\widehat{t},y-1} \text{, if } y \neq 'first\_period' \\ * + duration\_period_{y} \cdot EMISS_{n,e,\widehat{t},y} \\ From c54da7dd8d734c250014f3f8153089a65da3f8a8 Mon Sep 17 00:00:00 2001 From: Unknown Date: Tue, 9 Nov 2021 10:05:55 +0100 Subject: [PATCH 27/47] switched order of terms in EMISSION_POOL_EQUIVALENCE and fixed name in documentation switching order of terms has no impact on results, but is more logical when presenting the material --- message_ix/model/MESSAGE/model_core.gms | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/message_ix/model/MESSAGE/model_core.gms b/message_ix/model/MESSAGE/model_core.gms index efd5fed1e..6e495140d 100644 --- a/message_ix/model/MESSAGE/model_core.gms +++ b/message_ix/model/MESSAGE/model_core.gms @@ -1889,8 +1889,8 @@ EMISSION_CONSTRAINT(node,type_emission,type_tec,type_year)$is_bound_emission(nod * * .. _emission_pool: * -* Equation EMISSION_POOL -* """""""""""""""""""""" +* Equation EMISSION_POOL_EQUIVALENCE +* """""""""""""""""""""""""""""""""" * :math:`EMISS\_POOL\_EQUIVALENCE_{n,e,\widehat{t},y}` is the atmospheric pool at node :math:`n` * for emission :math:`e` from technology set :math:`\widehat{t}` in year :math:`y`. * Via :math:`historical\_emission\_pool` past emissions can be attributed to node :math:`n`, establishing the initial @@ -1902,22 +1902,22 @@ EMISSION_CONSTRAINT(node,type_emission,type_tec,type_year)$is_bound_emission(nod * EMISS\_POOL_{n,e,\widehat{t},y} = * \frac{1}{ 1 + emission\_sink\_rate_{n,e,\widehat{t},y} \cdot duration\_period_{y}} \cdot \\ * \begin{array}{l} -* ( EMISS\_POOL_{n,e,\widehat{t},y-1} \text{, if } y \neq 'first\_period' \\ -* + duration\_period_{y} \cdot EMISS_{n,e,\widehat{t},y} \\ -* + historical\_emission\_pool_{n,e,\widehat{t},y-1} \text{, if } y = 'first\_period' ) +* ( historical\_emission\_pool_{n,e,\widehat{t},y-1} \text{, if } y = 'first\_period' \\ +* + EMISS\_POOL_{n,e,\widehat{t},y-1} \text{, if } y \neq 'first\_period' \\ +* + duration\_period_{y} \cdot EMISS_{n,e,\widehat{t},y} ) * \end{array} * *** EMISSION_POOL_EQUIVALENCE(node,emission,type_tec,year)$is_emission_sink_rate(node,emission,type_tec,year).. EMISS_POOL(node,emission,type_tec,year) =G= +* emission pool from historical period if year == firstmodelyear + historical_emission_pool(node,emission,type_tec,year_all2)$first_period(year) * emission pool from previous period if year != firstmodelyear - SUM(year_all2$( seq_period(year_all2,year) ), + + SUM(year_all2$( seq_period(year_all2,year) ), EMISS_POOL(node,emission,type_tec,year_all2)$(model_horizon(year_all2) AND NOT first_period(year)) * emission additions in current period + duration_period(year) * EMISS(node,emission,type_tec,year) -* emission pool from historical period if year == firstmodelyear - + historical_emission_pool(node,emission,type_tec,year_all2)$first_period(year) ) / (1 + emission_sink_rate(node,emission,type_tec,year) * duration_period(year)) ; From 02ba2e687cfa04587e77d2f7d40c3994a6fc5e2b Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 9 Nov 2021 10:57:06 +0100 Subject: [PATCH 28/47] Move the mapping of years to the top of equation block --- message_ix/model/MESSAGE/model_core.gms | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/message_ix/model/MESSAGE/model_core.gms b/message_ix/model/MESSAGE/model_core.gms index 6e495140d..64fb79284 100644 --- a/message_ix/model/MESSAGE/model_core.gms +++ b/message_ix/model/MESSAGE/model_core.gms @@ -1911,11 +1911,11 @@ EMISSION_CONSTRAINT(node,type_emission,type_tec,type_year)$is_bound_emission(nod EMISSION_POOL_EQUIVALENCE(node,emission,type_tec,year)$is_emission_sink_rate(node,emission,type_tec,year).. EMISS_POOL(node,emission,type_tec,year) =G= + SUM(year_all2$( seq_period(year_all2,year) ), * emission pool from historical period if year == firstmodelyear historical_emission_pool(node,emission,type_tec,year_all2)$first_period(year) * emission pool from previous period if year != firstmodelyear - + SUM(year_all2$( seq_period(year_all2,year) ), - EMISS_POOL(node,emission,type_tec,year_all2)$(model_horizon(year_all2) AND NOT first_period(year)) + + EMISS_POOL(node,emission,type_tec,year_all2)$(model_horizon(year_all2) AND NOT first_period(year)) * emission additions in current period + duration_period(year) * EMISS(node,emission,type_tec,year) ) / (1 + emission_sink_rate(node,emission,type_tec,year) * duration_period(year)) From b9b4cc7d588bf2dff95bed59660b7a48ae91c6f1 Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 9 Nov 2021 10:58:08 +0100 Subject: [PATCH 29/47] Correct the reporting of PRICE_EMISSION_POOL --- message_ix/model/MESSAGE/model_solve.gms | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/message_ix/model/MESSAGE/model_solve.gms b/message_ix/model/MESSAGE/model_solve.gms index 5f45eac8b..adf833e3f 100644 --- a/message_ix/model/MESSAGE/model_solve.gms +++ b/message_ix/model/MESSAGE/model_solve.gms @@ -60,11 +60,7 @@ EMISSION_CONSTRAINT.m(node,type_emission,type_tec,type_year)$( PRICE_EMISSION.l(node,type_emission,type_tec,year)$( PRICE_EMISSION.l(node,type_emission,type_tec,year) = - inf ) = 0 ; -* rescale the dual of the emission constraint to account that the constraint is defined on the average year, not total -EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year)$( - EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year) ) = - EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year) / df_period(year) ; - +* rescale the dual of the emission pool constraint to account for the discount factor per period duration PRICE_EMISSION_POOL.l(node,type_emission,type_tec,year) = - EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year) * duration_period(year) ; From 41a83726fe61dad43635556981d50d34098ec5ba Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 10 Nov 2021 13:17:25 +0100 Subject: [PATCH 30/47] Account for duration_period in reporting of PRICE_EMISSION_POOL --- message_ix/model/MESSAGE/model_solve.gms | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/message_ix/model/MESSAGE/model_solve.gms b/message_ix/model/MESSAGE/model_solve.gms index adf833e3f..c2ab1ec68 100644 --- a/message_ix/model/MESSAGE/model_solve.gms +++ b/message_ix/model/MESSAGE/model_solve.gms @@ -60,8 +60,12 @@ EMISSION_CONSTRAINT.m(node,type_emission,type_tec,type_year)$( PRICE_EMISSION.l(node,type_emission,type_tec,year)$( PRICE_EMISSION.l(node,type_emission,type_tec,year) = - inf ) = 0 ; -* rescale the dual of the emission pool constraint to account for the discount factor per period duration - PRICE_EMISSION_POOL.l(node,type_emission,type_tec,year) = +* rescale the dual of the emission pool constraint to account for the discount factor and period duration +EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year)$( + EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year)) = + EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year) / df_period(year); + +PRICE_EMISSION_POOL.l(node,type_emission,type_tec,year) = - EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year) * duration_period(year) ; PRICE_EMISSION_POOL.l(node,type_emission,type_tec,year)$( From aceb928eacbd9bf0ba6efb0fca7c61ea4c4efe6b Mon Sep 17 00:00:00 2001 From: Paul Natsuo Kishimoto Date: Tue, 16 Nov 2021 11:11:47 +0100 Subject: [PATCH 31/47] Remove manual init/setting of new sets/pars in .tests.test_emission_pool --- message_ix/tests/test_emission_pool.py | 39 +------------------------- 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/message_ix/tests/test_emission_pool.py b/message_ix/tests/test_emission_pool.py index a9ec74856..4ff1d123c 100644 --- a/message_ix/tests/test_emission_pool.py +++ b/message_ix/tests/test_emission_pool.py @@ -7,35 +7,6 @@ def prep_scenario(s, test_mp): s.check_out() - # Initialize parameters - new_par = { - "historical_emission_pool": ["node", "emission", "type_tec", "year"], - "emission_sink_rate": ["node", "emission", "type_tec", "year"], - "bound_emission_pool": ["node", "type_emission", "type_tec", "year"], - "tax_emission_pool": ["node", "type_emission", "type_tec", "year"], - } - for par, idx in new_par.items(): - if par not in s.par_list(): - s.init_par(par, idx) - - # Initialize sets - new_set = { - "is_bound_emission_pool": ["node", "type_emission", "type_tec", "year"], - "is_emission_sink_rate": ["node", "emission", "type_tec", "year"], - } - for sets, idx in new_set.items(): - if sets not in s.set_list(): - s.init_set(sets, idx) - - # Initialize variables - new_var = { - "EMISS_POOL": ["node", "emission", "type_tec", "year"], - "PRICE_EMISSION_POOL": ["node", "type_emission", "type_tec", "year"], - } - for var, idx in new_var.items(): - if var not in s.var_list(): - s.init_var(var, idx) - # Add emission parameters s.add_set("emission", "CO2") s.add_cat("emission", "GHG", "CO2") @@ -82,7 +53,6 @@ def prep_scenario(s, test_mp): } ) s.add_par("emission_sink_rate", df) - s.add_set("is_emission_sink_rate", df.drop(["value", "unit"], axis=1)) s.commit("prep test sceanrios") @@ -126,8 +96,7 @@ def test_add_setup(test_mp): pdt.assert_frame_equal(exp, obs, check_dtype=False) - # Ensure that set is_emission_sink_rate - # has been added. + # Ensure that set is_emission_sink_rate has been added exp = exp.drop(["value", "unit"], axis=1) obs = s.set("is_emission_sink_rate") @@ -184,11 +153,6 @@ def test_tax_emission_pool_world(test_mp): df["node"] = "World" s.add_par(par, df) - for set in ["is_emission_sink_rate"]: - df = s.set(set) - df["node"] = "World" - s.add_set(set, df) - df = pd.DataFrame( { "node": "World", @@ -243,7 +207,6 @@ def test_bound_emission_pool(test_mp): } ) s.add_par("bound_emission_pool", df) - s.add_set("is_bound_emission_pool", df.drop(["value", "unit"], axis=1)) s.commit("bound_emission_pool added") s.solve(var_list=["EMISS_POOL", "PRICE_EMISSION_POOL"]) From f6df46057ea696934d55534efea54e40e4cbce3e Mon Sep 17 00:00:00 2001 From: Paul Natsuo Kishimoto Date: Tue, 16 Nov 2021 11:12:44 +0100 Subject: [PATCH 32/47] =?UTF-8?q?Remove=20solve(var=5Flist=3D=E2=80=A6)=20?= =?UTF-8?q?for=20new=20vars=20in=20.tests.test=5Femission=5Fpool?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- message_ix/tests/test_emission_pool.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/message_ix/tests/test_emission_pool.py b/message_ix/tests/test_emission_pool.py index 4ff1d123c..81d7ab85a 100644 --- a/message_ix/tests/test_emission_pool.py +++ b/message_ix/tests/test_emission_pool.py @@ -122,7 +122,7 @@ def test_tax_emission_pool(test_mp): s.add_par("tax_emission_pool", df) s.commit("tax_emission_pool added") - s.solve(var_list=["EMISS_POOL", "PRICE_EMISSION_POOL"]) + s.solve() exp = pd.DataFrame( { @@ -166,7 +166,7 @@ def test_tax_emission_pool_world(test_mp): s.add_par("tax_emission_pool", df) s.commit("tax_emission_pool added") - s.solve(var_list=["EMISS_POOL", "PRICE_EMISSION_POOL"]) + s.solve() exp = pd.DataFrame( { @@ -209,7 +209,7 @@ def test_bound_emission_pool(test_mp): s.add_par("bound_emission_pool", df) s.commit("bound_emission_pool added") - s.solve(var_list=["EMISS_POOL", "PRICE_EMISSION_POOL"]) + s.solve() exp = pd.DataFrame( { From 2b574f6fe80bb4b84d656d32f95b16edcf35eed5 Mon Sep 17 00:00:00 2001 From: Paul Natsuo Kishimoto Date: Tue, 16 Nov 2021 11:15:21 +0100 Subject: [PATCH 33/47] Reflow comments/docstrings in .models --- message_ix/models.py | 75 +++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 39 deletions(-) diff --git a/message_ix/models.py b/message_ix/models.py index 21329f488..d47c7d3c1 100644 --- a/message_ix/models.py +++ b/message_ix/models.py @@ -56,8 +56,8 @@ def item(ix_type, expr): ... idx_names=["node_loc", "technology", "year_act"] ... ) """ - # Split expr on spaces. For each dimension, use an abbreviation (if one) - # exists, else the set name for both idx_sets and idx_names + # Split expr on spaces. For each dimension, use an abbreviation (if one) exists, + # else the set name for both idx_sets and idx_names sets, names = zip(*[_ABBREV.get(dim, (dim, dim)) for dim in expr.split()]) # Assemble the result @@ -102,8 +102,8 @@ def item(ix_type, expr): # # Indexed sets "addon": dict(ix_type="set", idx_sets=["technology"]), - # commented: in test_solve_legacy_scenario(), ixmp_source complains that - # the item already exists + # commented: in test_solve_legacy_scenario(), ixmp_source complains that the item + # already exists # "balance_equality": item("set", "c l"), "cat_addon": dict( ix_type="set", @@ -272,10 +272,12 @@ def item(ix_type, expr): "time_order": dict(ix_type="par", idx_sets=["lvl_temporal", "time"]), "var_cost": item("par", "nl t yv ya m h"), # - # commented: for both variables and equations, ixmp_source requires that - # the `idx_sets` and `idx_names` parameters be empty, but then internally - # uses the correct sets and names to initialize. - # TODO adjust ixmp_source to accept these values, then uncomment. + # For certain variables and equations, the Java code of ixmp_source requires that + # the `idx_sets` and `idx_names` parameters be empty, but then internally uses the + # correct sets and names to initialize. For other (newer) var/equ, e.g. + # "EMISS_POOL", the Java code has no dedicated code, so this quirk does not occur. + # + # TODO Uncomment the items below once ixmp_source is adjusted or replaced. # # Variables # @@ -328,8 +330,8 @@ class GAMSModel(ixmp.model.gams.GAMSModel): _template("output", "MsgIterationReport_{case}.gdx") ), ], - # Disable the feature to put input/output GDX files, list files, etc. - # in a temporary directory + # Disable the feature to put input/output GDX files, list files, etc. in a + # temporary directory "use_temp_dir": False, }, ixmp.model.gams.GAMSModel.defaults, @@ -357,23 +359,21 @@ def __init__(self, name=None, **model_options): def run(self, scenario): """Execute the model. - GAMSModel creates a file named ``cplex.opt`` in the model directory - containing the options in :obj:`DEFAULT_CPLEX_OPTIONS`, or any - overrides passed to :meth:`~message_ix.Scenario.solve`. + GAMSModel creates a file named ``cplex.opt`` in the model directory containing + the options in :obj:`DEFAULT_CPLEX_OPTIONS`, or any overrides passed to + :meth:`~message_ix.Scenario.solve`. - .. warning:: GAMSModel can solve Scenarios in two or more Python - processes simultaneously; but using *different* CPLEX options in - each process may produced unexpected results. + .. warning:: GAMSModel can solve Scenarios in two or more Python processes + simultaneously; but using *different* CPLEX options in each process may + produced unexpected results. """ - # If two runs are kicked off simulatenously with the same - # self.model_dir, then they will try to write the same optfile, and may - # write different contents. - # - # TODO Re-enable the 'use_temp_dir' feature from ixmp.GAMSModel - # (disabled above). Then cplex.opt will be specific to that - # directory. # Write CPLEX options into an options file + # FIXME If two runs are kicked off simulatenously with the same self.model_dir, + # then they will try to write the same optfile, and may write different + # contents. To fix, re-enable the 'use_temp_dir' feature from + # ixmp.GAMSModel (disabled above). Then cplex.opt will be specific to + # that directory. optfile = self.model_dir / "cplex.opt" lines = ("{} = {}".format(*kv) for kv in self.cplex_opts.items()) optfile.write_text("\n".join(lines)) @@ -381,11 +381,10 @@ def run(self, scenario): try: result = super().run(scenario) finally: - # Remove the optfile regardless of whether the run completed - # without error. The file may have been removed already by another - # run (in a separate process) that completed before this one. - # py37 compat: check for existence instead of using - # unlink(missing_ok=True) + # Remove the optfile regardless of whether the run completed without error. + # The file may have been removed already by another run (in a separate + # process) that completed before this one. + # py37 compat: check for existence instead of using unlink(missing_ok=True) if optfile.exists(): optfile.unlink() @@ -403,15 +402,14 @@ class MACRO(GAMSModel): name = "MACRO" - #: MACRO uses the GAMS ``break;`` statement, and thus requires GAMS 24.8.1 - #: or later. + #: MACRO uses the GAMS ``break;`` statement, and thus requires GAMS 24.8.1 or later GAMS_min_version = "24.8.1" def __init__(self, *args, **kwargs): version = ixmp.model.gams.gams_version() if version < self.GAMS_min_version: message = ( - "{0.name} requires GAMS >= {0.GAMS_min_version}; " "found {1}" + "{0.name} requires GAMS >= {0.GAMS_min_version}; found {1}" ).format(self, version) raise RuntimeError(message) @@ -420,12 +418,11 @@ def __init__(self, *args, **kwargs): @classmethod def initialize(cls, scenario, with_data=False): """Initialize the model structure.""" - # NB some scenarios already have these items. This method simply adds - # any missing items. - - # FIXME the Java code under the JDBCBackend (ixmp_source) refuses to - # initialize these items with specified idx_sets—even if the - # sets are correct. + # NB some scenarios already have these items. This method simply adds any + # missing items. + # + # FIXME the Java code under the JDBCBackend (ixmp_source) refuses to initialize + # these items with specified idx_sets—even if the sets are correct. items = deepcopy(MACRO_ITEMS) for name in "C", "COST_NODAL", "COST_NODAL_NET", "DEMAND", "GDP", "I": items[name].pop("idx_sets") @@ -440,8 +437,8 @@ class MESSAGE_MACRO(MACRO): name = "MESSAGE-MACRO" def __init__(self, *args, **kwargs): - # Remove M-M iteration options from kwargs and convert to GAMS - # command-line options + # Remove M-M iteration options from kwargs and convert to GAMS command-line + # options mm_iter_args = [] for name in "convergence_criterion", "max_adjustment", "max_iteration": try: From b53bfc2de222bdc6616e602cae461d01c00cf866 Mon Sep 17 00:00:00 2001 From: Paul Natsuo Kishimoto Date: Tue, 16 Nov 2021 11:19:16 +0100 Subject: [PATCH 34/47] Add EMISS_POOL, PRICE_EMISSION_POOL to MESSAGE_ITEMS --- message_ix/models.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/message_ix/models.py b/message_ix/models.py index d47c7d3c1..ded798289 100644 --- a/message_ix/models.py +++ b/message_ix/models.py @@ -299,6 +299,9 @@ def item(ix_type, expr): # "REL": item("var", "relation nr yr"), # # Stock # "STOCK": item("var", "n c l y"), + # Emissions pools + "EMISS_POOL": item("var", "n e type_tec y"), + "PRICE_EMISSION_POOL": item("var", "n type_emission type_tec y"), # # # Equations # # Commodity balance From 8a06411fc9ad0d8a8aa43909a936e998fedaf9bf Mon Sep 17 00:00:00 2001 From: Paul Natsuo Kishimoto Date: Tue, 16 Nov 2021 11:31:10 +0100 Subject: [PATCH 35/47] Add {GAMSModel,MESSAGE}.enforce to enforce consistency of mapping sets --- message_ix/models.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/message_ix/models.py b/message_ix/models.py index ded798289..596f7e5b1 100644 --- a/message_ix/models.py +++ b/message_ix/models.py @@ -351,6 +351,13 @@ def initialize(cls, scenario): # Initialize the ixmp items cls.initialize_items(scenario, MESSAGE_ITEMS) + @staticmethod + def enforce(scenario): + """Enforce data consistency in `scenario`.""" + # Implemented in MESSAGE sub-class, below + # TODO make this an optional method of the ixmp.model.base.Model abstract class + pass + def __init__(self, name=None, **model_options): # Update the default options with any user-provided options model_options.setdefault("model_dir", config.get("message model dir")) @@ -370,6 +377,9 @@ def run(self, scenario): simultaneously; but using *different* CPLEX options in each process may produced unexpected results. """ + # Ensure the data in `scenario` is consistent with the MESSAGE formulation + # TODO move this call to ixmp.model.base.Model.run(); remove here + self.enforce(scenario) # Write CPLEX options into an options file # FIXME If two runs are kicked off simulatenously with the same self.model_dir, @@ -399,6 +409,30 @@ class MESSAGE(GAMSModel): name = "MESSAGE" + @staticmethod + def enforce(scenario): + """Enforce data consistency in `scenario`.""" + # Check masks ("mapping sets") that indicate which elements of corresponding + # parameters are active/non-zero. Note that there are other masks currently + # handled in JDBCBackend. For the moment, this code does not backstop that + # behaviour. + # TODO Extend to handle all masks, e.g. for new backends. + for par_name in ("bound_emission_pool", "emission_sink_rate"): + # Name of the corresponding set + set_name = f"is_{par_name}" + + # Existing and expected contents + existing = scenario.set(set_name) + expected = scenario.par(par_name).drop(columns=["value", "unit"]) + + if existing.equals(expected): + continue # Contents are as expected; do nothing + + # Not consistent; empty and then re-populate the set + with scenario.transact(f"Enforce consistency of {set_name} and {par_name}"): + scenario.remove_set(set_name, existing) + scenario.add_set(set_name, expected) + class MACRO(GAMSModel): """Model class for MACRO.""" From 3e2445fbeb4130c8705afbd13421645555f4b148 Mon Sep 17 00:00:00 2001 From: Paul Natsuo Kishimoto Date: Tue, 16 Nov 2021 11:31:50 +0100 Subject: [PATCH 36/47] Ensure variables in MESSAGE_ITEMS are always read by JDBCBackend --- message_ix/models.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/message_ix/models.py b/message_ix/models.py index 596f7e5b1..12e1c5450 100644 --- a/message_ix/models.py +++ b/message_ix/models.py @@ -366,6 +366,17 @@ def __init__(self, name=None, **model_options): super().__init__(name, **model_options) + # Extend `var_list`. JDBCBackend does not automatically read vars from the model + # solution GDX file, even when they exist in the Scenario. Ensure the vars that + # are part of the MESSAGE scheme are always read. + self.var_list = self.var_list or [] + # Iterate over names of "var" items that are not already in `var_list` + for name, _ in filter( + lambda kv: kv[1]["ix_type"] == "var" and kv[0] not in self.var_list, + MESSAGE_ITEMS.items(), + ): + self.var_list.append(name) + def run(self, scenario): """Execute the model. From 349c8a0a6859dd802361f9a77b15d04000d489a0 Mon Sep 17 00:00:00 2001 From: FRICKO Oliver Date: Tue, 16 Nov 2021 13:59:09 +0100 Subject: [PATCH 37/47] Ensure all tests pass --- message_ix/tests/test_emission_pool.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/message_ix/tests/test_emission_pool.py b/message_ix/tests/test_emission_pool.py index 81d7ab85a..15146c2ac 100644 --- a/message_ix/tests/test_emission_pool.py +++ b/message_ix/tests/test_emission_pool.py @@ -235,10 +235,10 @@ def test_bound_emission_pool(test_mp): "type_emission": "GHG", "type_tec": "all", "year": [700, 720], - "lvl": [1.8271384, 2.939589], + "lvl": [1.452659, 2.337108], # When changing the capacity factor of wind to 0.36, # comment in the line below. - # "lvl": [27.397316, 44.070817], + # "lvl": [21.782120, 35.038315], "mrg": 0.0, } ) From 038f2db78ef359d2cfa6a52ea233795b4826d0f1 Mon Sep 17 00:00:00 2001 From: FRICKO Oliver Date: Tue, 16 Nov 2021 14:00:09 +0100 Subject: [PATCH 38/47] Remove parameter/set initialization --- .../westeros/westeros_emission_pools.ipynb | 201 +++--------------- 1 file changed, 35 insertions(+), 166 deletions(-) diff --git a/tutorial/westeros/westeros_emission_pools.ipynb b/tutorial/westeros/westeros_emission_pools.ipynb index dd5f84c03..2bc44661e 100644 --- a/tutorial/westeros/westeros_emission_pools.ipynb +++ b/tutorial/westeros/westeros_emission_pools.ipynb @@ -15,22 +15,9 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "application/javascript": [ - "IPython.OutputArea.prototype._should_scroll = function(lines) { return false; }" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "import pandas as pd\n", "import ixmp\n", @@ -43,7 +30,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -52,7 +39,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -66,7 +53,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -85,7 +72,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -121,7 +108,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -129,40 +116,6 @@ " value=500., unit='MtCO2')" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Initialize parameters" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "new_par = {\"historical_emission_pool\": ['node', 'emission', 'type_tec', 'year'],\n", - " \"emission_sink_rate\": ['node', 'emission', 'type_tec', 'year'],\n", - " \"bound_emission_pool\": [\"node\", \"type_emission\", \"type_tec\", \"year\"],\n", - " \"tax_emission_pool\": [\"node\", \"type_emission\", \"type_tec\", \"year\"]}\n", - "for par, idx in new_par.items():\n", - " if par not in scen.par_list():\n", - " scen.init_par(par, idx)\n", - "\n", - "new_set = {\n", - " \"is_bound_emission_pool\": [\"node\", \"type_emission\", \"type_tec\", \"year\"],\n", - " \"is_emission_sink_rate\": ['node', 'emission', 'type_tec', 'year']}\n", - "for sets, idx in new_set.items():\n", - " if sets not in scen.set_list():\n", - " scen.init_set(sets, idx)\n", - "\n", - "new_var = {'EMISS_POOL': ['node', 'emission', 'type_tec', 'year']}\n", - "for var, idx in new_var.items():\n", - " if var not in scen.var_list():\n", - " scen.init_var(var, idx)" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -172,7 +125,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -198,7 +151,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -222,7 +175,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -240,11 +193,11 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "add_tep = True\n", + "add_tep = False\n", "if add_tep:\n", " df = pd.DataFrame({\n", " 'node': 'Westeros',\n", @@ -267,7 +220,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -279,12 +232,7 @@ " for par in ['emission_sink_rate', 'historical_emission_pool']:\n", " df = scen.par(par)\n", " df[\"node\"] = 'World'\n", - " scen.add_par(par, df)\n", - " \n", - " for s in ['is_emission_sink_rate']:\n", - " df = scen.set(s)\n", - " df[\"node\"] = 'World'\n", - " scen.add_set(s, df) \n", + " scen.add_par(par, df) \n", " \n", " df = pd.DataFrame({\n", " 'node': 'World',\n", @@ -307,11 +255,11 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "add_epb = False\n", + "add_epb = True\n", "if add_epb:\n", " df = pd.DataFrame({\n", " 'node': 'Westeros',\n", @@ -322,10 +270,6 @@ " 'unit': '???'\n", " })\n", " scen.add_par('bound_emission_pool', df)\n", - "\n", - " # Adding mapping sets of new parameters\n", - " if not df.empty:\n", - " scen.add_set('is_bound_emission_pool', df.drop(['value', 'unit'], axis=1))\n", " \n", " # Remove bound_emission\n", " df = scen.par('bound_emission')\n", @@ -342,7 +286,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -352,29 +296,18 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "scen.solve(var_list=['EMISS_POOL'], case=case)" + "scen.solve(var_list=['EMISS_POOL', 'PRICE_EMISSION_POOL'], case=case)" ] }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "303294.28125" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "scen.var('OBJ')['lvl']" ] @@ -388,7 +321,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -410,86 +343,22 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
nodeemissiontype_tecyearlvlmrg
0WesterosCO2all70087803.0977370.0
1WesterosCO2all71085984.9505490.0
2WesterosCO2all72084610.3670450.0
\n", - "
" - ], - "text/plain": [ - " node emission type_tec year lvl mrg\n", - "0 Westeros CO2 all 700 87803.097737 0.0\n", - "1 Westeros CO2 all 710 85984.950549 0.0\n", - "2 Westeros CO2 all 720 84610.367045 0.0" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "scen.var('EMISS_POOL')" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "scen.var('PRICE_EMISSION_POOL')" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -499,7 +368,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -523,7 +392,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.2" + "version": "3.7.9" } }, "nbformat": 4, From 2e40d754e34710252cc0a751aa4fedf0876eb248 Mon Sep 17 00:00:00 2001 From: FRICKO Oliver Date: Tue, 16 Nov 2021 17:29:31 +0100 Subject: [PATCH 39/47] Adjust test and tutorial to work with changes from rebase --- message_ix/tests/test_emission_pool.py | 26 +- .../westeros/westeros_emission_pools.ipynb | 228 +++++++++++++++--- 2 files changed, 198 insertions(+), 56 deletions(-) diff --git a/message_ix/tests/test_emission_pool.py b/message_ix/tests/test_emission_pool.py index 15146c2ac..5ed3d7367 100644 --- a/message_ix/tests/test_emission_pool.py +++ b/message_ix/tests/test_emission_pool.py @@ -130,7 +130,7 @@ def test_tax_emission_pool(test_mp): "emission": "CO2", "type_tec": "all", "year": [700, 710, 720], - "lvl": [86874.248590, 80820.292479, 76971.707123], + "lvl": [85154.242090, 78031.405954, 74315.624718], "mrg": 0.0, } ) @@ -175,12 +175,12 @@ def test_tax_emission_pool_world(test_mp): "type_tec": "all", "year": [700, 710, 720, 700, 710, 720], "lvl": [ - 86874.248590, - 80820.292479, - 76971.707123, - 86874.248590, - 80820.292479, - 76971.707123, + 85154.242090, + 78031.405954, + 74315.624718, + 85154.242090, + 78031.405954, + 74315.624718, ], "mrg": 0.0, } @@ -217,10 +217,7 @@ def test_bound_emission_pool(test_mp): "emission": "CO2", "type_tec": "all", "year": [700, 710, 720], - "lvl": [87000, 85476.734072, 85000], - # When changing the capacity factor of wind to 0.36, - # comment in the line below. - # "lvl": [87000, 85975.299326, 85000], + "lvl": [86254.747976, 83545.115216, 85000], "mrg": 0.0, } ) @@ -234,11 +231,8 @@ def test_bound_emission_pool(test_mp): "node": "Westeros", "type_emission": "GHG", "type_tec": "all", - "year": [700, 720], - "lvl": [1.452659, 2.337108], - # When changing the capacity factor of wind to 0.36, - # comment in the line below. - # "lvl": [21.782120, 35.038315], + "year": [720], + "lvl": [33.075572], "mrg": 0.0, } ) diff --git a/tutorial/westeros/westeros_emission_pools.ipynb b/tutorial/westeros/westeros_emission_pools.ipynb index 2bc44661e..a8a8a814f 100644 --- a/tutorial/westeros/westeros_emission_pools.ipynb +++ b/tutorial/westeros/westeros_emission_pools.ipynb @@ -15,9 +15,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "application/javascript": [ + "IPython.OutputArea.prototype._should_scroll = function(lines) { return false; }" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "import pandas as pd\n", "import ixmp\n", @@ -30,7 +43,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -39,7 +52,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -53,7 +66,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -72,7 +85,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -108,7 +121,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -125,7 +138,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -151,7 +164,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -166,22 +179,13 @@ "scen.add_par('emission_sink_rate', df)" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Add is_sinkrate for model-periods" - ] - }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ - "# Adding mapping sets of new parameters\n", - "if not df.empty:\n", - " scen.add_set('is_emission_sink_rate', df.drop(['value', 'unit'], axis=1))" + "case = \"carbon_pool_accounting\"" ] }, { @@ -193,7 +197,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ @@ -220,7 +224,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ @@ -239,7 +243,7 @@ " 'type_emission': 'CO2',\n", " 'type_tec': 'all',\n", " 'year': [700, 710, 720],\n", - " 'value': [2.92, 0, 1.42],\n", + " 'value': [500, 500, 500],\n", " 'unit': '???'\n", " })\n", " scen.add_par('tax_emission_pool', df) \n", @@ -255,7 +259,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": {}, "outputs": [], "source": [ @@ -277,6 +281,13 @@ " case = \"bound_emission\"" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "markdown", "metadata": {}, @@ -286,7 +297,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "metadata": {}, "outputs": [], "source": [ @@ -296,7 +307,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "metadata": {}, "outputs": [], "source": [ @@ -305,9 +316,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "221792.71875" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "scen.var('OBJ')['lvl']" ] @@ -321,19 +343,19 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "# WITHOUT any constraints EMISS_POOL should have results:\n", - "# 700 88299.738226\n", - "# 710 86699.717263\n", - "# 720 84447.695837 \n", + "# 700 86254.747976\n", + "# 710 83581.678489\n", + "# 720 85134.173863 \n", " \n", "# WITH `tax_emission_pool' EMISS_POOL should have results:\n", - "# 700 86874.248590\n", - "# 710 80820.292479\n", - "# 720 76971.707123\n", + "# 700 85154.242090\n", + "# 710 78031.405954\n", + "# 720 74315.624718\n", "\n", "# WITH `bound_emission_pool' EMISS_POOL should have results:\n", "# 700 87000\n", @@ -343,18 +365,144 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
nodeemissiontype_tecyearlvlmrg
0WesterosCO2all70086254.7479760.0
1WesterosCO2all71083545.1152160.0
2WesterosCO2all72085000.0000000.0
\n", + "
" + ], + "text/plain": [ + " node emission type_tec year lvl mrg\n", + "0 Westeros CO2 all 700 86254.747976 0.0\n", + "1 Westeros CO2 all 710 83545.115216 0.0\n", + "2 Westeros CO2 all 720 85000.000000 0.0" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "scen.var('EMISS_POOL')" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
nodetype_emissiontype_tecyearlvlmrg
0WesterosGHGall72033.0755720.0
\n", + "
" + ], + "text/plain": [ + " node type_emission type_tec year lvl mrg\n", + "0 Westeros GHG all 720 33.075572 0.0" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "scen.var('PRICE_EMISSION_POOL')" ] @@ -368,7 +516,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "metadata": {}, "outputs": [], "source": [ From fcc57956e1f1afc0d74041a2b4e93fbab201f6b7 Mon Sep 17 00:00:00 2001 From: FRICKO Oliver Date: Tue, 16 Nov 2021 17:41:24 +0100 Subject: [PATCH 40/47] Enhance test to check removal of 'is*' set is correct --- message_ix/tests/test_emission_pool.py | 38 ++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/message_ix/tests/test_emission_pool.py b/message_ix/tests/test_emission_pool.py index 5ed3d7367..8ae132cc2 100644 --- a/message_ix/tests/test_emission_pool.py +++ b/message_ix/tests/test_emission_pool.py @@ -240,3 +240,41 @@ def test_bound_emission_pool(test_mp): obs = s.var("PRICE_EMISSION_POOL") pdt.assert_frame_equal(exp, obs, check_dtype=False) + + +def test_bound_emission_pool_removal(test_mp): + s = make_westeros(test_mp, quiet=True) + prep_scenario(s, test_mp) + + s.check_out() + df = pd.DataFrame( + { + "node": "Westeros", + "type_emission": "GHG", + "type_tec": "all", + "year": [700, 710, 720], + "value": [87000, 86000, 85000], + "unit": "???", + } + ) + s.add_par("bound_emission_pool", df) + s.commit("bound_emission_pool added") + + # Ensure that bound has been added + obs = s.par("bound_emission_pool") + pdt.assert_frame_equal(df, obs, check_dtype=False) + + s.solve() + + # Ensure that is_ set for bound has been added upon solving + exp = df.drop(["value", "unit"], axis=1) + obs = s.set("is_bound_emission_pool") + pdt.assert_frame_equal(exp, obs, check_dtype=False) + + s.remove_solution() + s.check_out() + s.remove_par("bound_emission_pool", df) + s.commit("bound_emission_poll removed") + + obs = s.set("is_bound_emission_pool") + assert obs.empty is True From 2d7bac68633c8875b9b55a6670337bf259e66ea2 Mon Sep 17 00:00:00 2001 From: FRICKO Oliver Date: Wed, 17 Nov 2021 12:12:01 +0100 Subject: [PATCH 41/47] Extend emission_pool tests --- message_ix/tests/test_emission_pool.py | 122 +++++++++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/message_ix/tests/test_emission_pool.py b/message_ix/tests/test_emission_pool.py index 8ae132cc2..0b4bf6602 100644 --- a/message_ix/tests/test_emission_pool.py +++ b/message_ix/tests/test_emission_pool.py @@ -271,6 +271,7 @@ def test_bound_emission_pool_removal(test_mp): obs = s.set("is_bound_emission_pool") pdt.assert_frame_equal(exp, obs, check_dtype=False) + # Esnure that is_ set is removed when removing parameter s.remove_solution() s.check_out() s.remove_par("bound_emission_pool", df) @@ -278,3 +279,124 @@ def test_bound_emission_pool_removal(test_mp): obs = s.set("is_bound_emission_pool") assert obs.empty is True + + +def test_bound_emission_pool_modification_inc_yrs(test_mp): + s = make_westeros(test_mp, quiet=True) + prep_scenario(s, test_mp) + + s.check_out() + df = pd.DataFrame( + { + "node": "Westeros", + "type_emission": "GHG", + "type_tec": "all", + "year": [700, 710], + "value": [87000, 86000], + "unit": "???", + } + ) + s.add_par("bound_emission_pool", df) + s.commit("bound_emission_pool added") + + # Ensure that bound has been added + obs = s.par("bound_emission_pool") + pdt.assert_frame_equal(df, obs, check_dtype=False) + + s.solve() + + # Ensure that is_ set for bound has been added upon solving + exp = df.drop(["value", "unit"], axis=1) + obs = s.set("is_bound_emission_pool") + pdt.assert_frame_equal(exp, obs, check_dtype=False) + + # Now check that when the dataframe is extended, if the "is_" set + # is correctly modified + s.remove_solution() + s.check_out() + df = pd.DataFrame( + { + "node": "Westeros", + "type_emission": "GHG", + "type_tec": "all", + "year": [700, 710, 720], + "value": [87000, 86000, 85000], + "unit": "???", + } + ) + s.add_par("bound_emission_pool", df) + s.commit("bound_emission_pool added") + + # Ensure that bound has been added + obs = s.par("bound_emission_pool") + pdt.assert_frame_equal(df, obs, check_dtype=False) + + s.solve() + + # Ensure that is_ set for bound has been added upon solving + exp = df.drop(["value", "unit"], axis=1) + obs = s.set("is_bound_emission_pool") + pdt.assert_frame_equal(exp, obs, check_dtype=False) + + +def test_bound_emission_pool_modification_red_yrs(test_mp): + s = make_westeros(test_mp, quiet=True) + prep_scenario(s, test_mp) + + s.check_out() + df = pd.DataFrame( + { + "node": "Westeros", + "type_emission": "GHG", + "type_tec": "all", + "year": [700, 710, 720], + "value": [87000, 86000, 85000], + "unit": "???", + } + ) + s.add_par("bound_emission_pool", df) + s.commit("bound_emission_pool added") + + # Ensure that bound has been added + obs = s.par("bound_emission_pool") + pdt.assert_frame_equal(df, obs, check_dtype=False) + + s.solve() + + # Ensure that is_ set for bound has been added upon solving + exp = df.drop(["value", "unit"], axis=1) + obs = s.set("is_bound_emission_pool") + pdt.assert_frame_equal(exp, obs, check_dtype=False) + + # Now check that when the dataframe is extended, if the "is_" set + # is correctly modified + s.remove_solution() + s.check_out() + + # Remove existing + df = s.par("bound_emission_pool") + s.remove_par("bound_emission_pool", df) + + df = pd.DataFrame( + { + "node": "Westeros", + "type_emission": "GHG", + "type_tec": "all", + "year": [700, 710], + "value": [87000, 86000], + "unit": "???", + } + ) + s.add_par("bound_emission_pool", df) + s.commit("bound_emission_pool added") + + # Ensure that bound has been added + obs = s.par("bound_emission_pool") + pdt.assert_frame_equal(df, obs, check_dtype=False) + + s.solve() + + # Ensure that is_ set for bound has been added upon solving + exp = df.drop(["value", "unit"], axis=1) + obs = s.set("is_bound_emission_pool") + pdt.assert_frame_equal(exp, obs, check_dtype=False) From 9b615e18fce545212fd781eb2ce48382df05997c Mon Sep 17 00:00:00 2001 From: Behnam Date: Tue, 7 Dec 2021 11:27:21 +0100 Subject: [PATCH 42/47] Implement lower and upper bounds for emission pooling --- message_ix/model/MESSAGE/data_load.gms | 3 +- message_ix/model/MESSAGE/model_core.gms | 45 ++++++++++++++----- message_ix/model/MESSAGE/model_solve.gms | 12 ++--- message_ix/model/MESSAGE/parameter_def.gms | 7 ++- message_ix/model/MESSAGE/sets_maps_def.gms | 3 +- message_ix/models.py | 14 ++++-- .../westeros/westeros_emission_pools.ipynb | 7 ++- 7 files changed, 62 insertions(+), 29 deletions(-) diff --git a/message_ix/model/MESSAGE/data_load.gms b/message_ix/model/MESSAGE/data_load.gms index dd008ae42..85ed2c0e2 100644 --- a/message_ix/model/MESSAGE/data_load.gms +++ b/message_ix/model/MESSAGE/data_load.gms @@ -52,7 +52,8 @@ rating_bin, reliability_factor, peak_load_factor, flexibility_factor renewable_capacity_factor, renewable_potential * emission factors, bounds and taxes on emissions (including mapping sets) historical_emission, emission_factor, emission_scaling, is_bound_emission, bound_emission, tax_emission, -emission_sink_rate, is_emission_sink_rate, historical_emission_pool, tax_emission_pool, is_bound_emission_pool, bound_emission_pool, +emission_sink_rate, is_emission_sink_rate, historical_emission_pool, tax_emission_pool, +bound_emission_pool_up, is_bound_emission_pool_up, bound_emission_pool_lo, is_bound_emission_pool_lo, * historical values of new capacity investment, activity and extraction historical_new_capacity, historical_activity, historical_extraction * parameters for land-use model emulator diff --git a/message_ix/model/MESSAGE/model_core.gms b/message_ix/model/MESSAGE/model_core.gms index 64fb79284..f4713c4ab 100644 --- a/message_ix/model/MESSAGE/model_core.gms +++ b/message_ix/model/MESSAGE/model_core.gms @@ -115,17 +115,14 @@ Variables COST_NODAL(node, year_all) system costs at the node level over time * auxiliary variable for aggregate emissions by technology type and land-use model emulator EMISS(node,emission,type_tec,year_all) aggregate emissions by technology type and land-use model emulator +* regional emission pool + EMISS_POOL(node,emission,type_tec,year_all) nodal-regional-global emission pool size * auxiliary variable for left-hand side of relations (linear constraints) REL(relation,node,year_all) auxiliary variable for left-hand side of user-defined relations * change in the content of storage device STORAGE_CHARGE(node,tec,level,commodity,year_all,time) charging of storage in each timestep (negative for discharge) ; -Positive variables -* regional emission pool - EMISS_POOL(node,emission,type_tec,year_all) nodal-regional-global emission pool size -; - *** * .. _section_auxiliary_variable_def: * @@ -280,7 +277,8 @@ Equations EMISSION_EQUIVALENCE auxiliary equation to simplify the notation of emissions EMISSION_CONSTRAINT nodal-regional-global constraints on emissions (by category) EMISSION_POOL_EQUIVALENCE nodal-regional-global emission pool with carbon sink rate - EMISSION_POOL_CONSTRAINT nodal-regional-global constraints on emission pool (by type) + EMISSION_POOL_CONSTRAINT_UP nodal-regional-global upper bound on emission pool (by type) + EMISSION_POOL_CONSTRAINT_LO nodal-regional-global lower bound on emission pool (by type) LAND_CONSTRAINT constraint on total land use (linear combination of land scenarios adds up to 1) DYNAMIC_LAND_SCEN_CONSTRAINT_UP dynamic constraint on land scenario change (upper bound) DYNAMIC_LAND_SCEN_CONSTRAINT_LO dynamic constraint on land scenario change (lower bound) @@ -1922,28 +1920,51 @@ EMISSION_POOL_EQUIVALENCE(node,emission,type_tec,year)$is_emission_sink_rate(nod ; *** -* Bound on emission pool +* Upper bound on emission pool * ^^^^^^^^^^^^^^^^^^^^^^ * -* .. _emission_pool_constraint: +* .. _emission_pool_constraint_up: * -* Equation EMISSION_POOL_CONSTRAINT +* Equation EMISSION_POOL_CONSTRAINT_UP * """"""""""""""""""""""""""""""""" * This constraint enforces upper bounds on the emission pool. * * .. math:: * \sum_{e \in E(\widehat{e})} * emission\_scaling_{\widehat{e},e} \cdot EMISS\_POOL_{n,e,\widehat{t},y} -* \leq bound\_emission\_pool_{n,\widehat{e},\widehat{t},y} +* \leq bound\_emission\_pool\_up_{n,\widehat{e},\widehat{t},y} * *** -EMISSION_POOL_CONSTRAINT(node,type_emission,type_tec,year)$is_bound_emission_pool(node,type_emission,type_tec,year).. + +EMISSION_POOL_CONSTRAINT_UP(node,type_emission,type_tec,year)$is_bound_emission_pool_up(node,type_emission,type_tec,year).. SUM( (emission)$( cat_emission(type_emission,emission) ), emission_scaling(type_emission,emission) * EMISS_POOL(node,emission,type_tec,year) ) - =L= bound_emission_pool(node,type_emission,type_tec,year) ; + =L= bound_emission_pool_up(node,type_emission,type_tec,year) ; +*** +* Lower bound on emission pool +* ^^^^^^^^^^^^^^^^^^^^^^ +* +* .. _emission_pool_constraint_lo: +* +* Equation EMISSION_POOL_CONSTRAINT_LO +* """"""""""""""""""""""""""""""""" +* This constraint enforces upper bounds on the emission pool. +* +* .. math:: +* \sum_{e \in E(\widehat{e})} +* emission\_scaling_{\widehat{e},e} \cdot EMISS\_POOL_{n,e,\widehat{t},y} +* \geq bound\_emission\_pool\_lo_{n,\widehat{e},\widehat{t},y} +* +*** +EMISSION_POOL_CONSTRAINT_LO(node,type_emission,type_tec,year)$is_bound_emission_pool_lo(node,type_emission,type_tec,year).. + SUM( (emission)$( cat_emission(type_emission,emission) ), + emission_scaling(type_emission,emission) + * EMISS_POOL(node,emission,type_tec,year) + ) + =G= bound_emission_pool_lo(node,type_emission,type_tec,year) ; *----------------------------------------------------------------------------------------------------------------------* *** * .. _section_landuse_emulator: diff --git a/message_ix/model/MESSAGE/model_solve.gms b/message_ix/model/MESSAGE/model_solve.gms index c2ab1ec68..df6eea1ca 100644 --- a/message_ix/model/MESSAGE/model_solve.gms +++ b/message_ix/model/MESSAGE/model_solve.gms @@ -61,15 +61,15 @@ EMISSION_CONSTRAINT.m(node,type_emission,type_tec,type_year)$( PRICE_EMISSION.l(node,type_emission,type_tec,year) = - inf ) = 0 ; * rescale the dual of the emission pool constraint to account for the discount factor and period duration -EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year)$( - EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year)) = - EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year) / df_period(year); +EMISSION_POOL_CONSTRAINT_UP.m(node,type_emission,type_tec,year)$( + EMISSION_POOL_CONSTRAINT_UP.m(node,type_emission,type_tec,year)) = + EMISSION_POOL_CONSTRAINT_UP.m(node,type_emission,type_tec,year) / df_period(year); PRICE_EMISSION_POOL.l(node,type_emission,type_tec,year) = - - EMISSION_POOL_CONSTRAINT.m(node,type_emission,type_tec,year) * duration_period(year) + - EMISSION_POOL_CONSTRAINT_UP.m(node,type_emission,type_tec,year) * duration_period(year) ; - PRICE_EMISSION_POOL.l(node,type_emission,type_tec,year)$( - PRICE_EMISSION_POOL.l(node,type_emission,type_tec,year) = - inf ) = 0 ; +PRICE_EMISSION_POOL.l(node,type_emission,type_tec,year)$( + PRICE_EMISSION_POOL.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 ; diff --git a/message_ix/model/MESSAGE/parameter_def.gms b/message_ix/model/MESSAGE/parameter_def.gms index 798f3c56c..2bb2c58d9 100644 --- a/message_ix/model/MESSAGE/parameter_def.gms +++ b/message_ix/model/MESSAGE/parameter_def.gms @@ -594,7 +594,9 @@ Parameters * - ``node`` | ``emission`` | ``type_tec`` | ``year`` * * - tax_emission_pool * - ``node`` | ``type_emission`` | ``type_tec`` | ``year`` -* * - bound_emission_pool +* * - bound_emission_pool_up +* - ``node`` | ``type_emission`` | ``type_tec`` | ``type`` +* * - bound_emission_pool_lo * - ``node`` | ``type_emission`` | ``type_tec`` | ``type`` * * .. [#em_scaling] The parameter ``emission_scaling`` is the scaling factor to harmonize bounds or taxes across types of @@ -610,7 +612,8 @@ Parameters emission_sink_rate(node,emission,type_tec,year_all) emission sink rate for regional emission pool formulation historical_emission_pool(node,emission,type_tec,year_all) historical size of emission pool by technology type tax_emission_pool(node,type_emission,type_tec,year_all) emission pool tax - bound_emission_pool(node,type_emission,type_tec,year_all) upper bound on emission pool size + bound_emission_pool_up(node,type_emission,type_tec,year_all) upper bound on emission pool size + bound_emission_pool_lo(node,type_emission,type_tec,year_all) lower bound on emission pool size ; *----------------------------------------------------------------------------------------------------------------------* diff --git a/message_ix/model/MESSAGE/sets_maps_def.gms b/message_ix/model/MESSAGE/sets_maps_def.gms index ba8f01fc8..167a7da34 100644 --- a/message_ix/model/MESSAGE/sets_maps_def.gms +++ b/message_ix/model/MESSAGE/sets_maps_def.gms @@ -447,7 +447,8 @@ Sets is_bound_emission(node,type_emission,type_tec,type_year) flag whether emissions bound exists is_emission_sink_rate(node,emission,type_tec,year_all) flag whether emission sink rate exists for regional emission pool formulation - is_bound_emission_pool(node,type_emission,type_tec,year_all) flag whether emission pool bound exists for regional emission pool formulation + is_bound_emission_pool_up(node,type_emission,type_tec,year_all) flag whether upper emission pool bound exists for regional emission pool formulation + is_bound_emission_pool_lo(node,type_emission,type_tec,year_all) flag whether lower emission pool bound exists for regional emission pool formulation is_dynamic_land_scen_up(node,land_scenario,year_all) flag whether dynamic upper constraint on land-scenario change exists is_dynamic_land_scen_lo(node,land_scenario,year_all) flag whether dynamic lower constraint on land-scenario change exists diff --git a/message_ix/models.py b/message_ix/models.py index 12e1c5450..535d56ae2 100644 --- a/message_ix/models.py +++ b/message_ix/models.py @@ -115,7 +115,10 @@ def item(ix_type, expr): "cat_relation": item("set", "type_relation relation"), "cat_tec": item("set", "type_tec t"), "cat_year": item("set", "type_year y"), - "is_bound_emission_pool": dict( + "is_bound_emission_pool_up": dict( + ix_type="set", idx_sets=["node", "type_emission", "type_tec", "year"] + ), + "is_bound_emission_pool_lo": dict( ix_type="set", idx_sets=["node", "type_emission", "type_tec", "year"] ), "is_emission_sink_rate": dict( @@ -158,9 +161,12 @@ def item(ix_type, expr): "bound_activity_lo": item("par", "nl t ya m h"), "bound_activity_up": item("par", "nl t ya m h"), "bound_emission": item("par", "n type_emission type_tec type_year"), - "bound_emission_pool": dict( + "bound_emission_pool_up": dict( ix_type="par", idx_sets=["node", "type_emission", "type_tec", "year"] ), + "bound_emission_pool_lo": dict( + ix_type="par", idx_sets=["node", "type_emission", "type_tec", "year"] + ), "bound_extraction_up": item("par", "n c g y"), "bound_new_capacity_lo": item("par", "nl t yv"), "bound_new_capacity_up": item("par", "nl t yv"), @@ -428,7 +434,9 @@ def enforce(scenario): # handled in JDBCBackend. For the moment, this code does not backstop that # behaviour. # TODO Extend to handle all masks, e.g. for new backends. - for par_name in ("bound_emission_pool", "emission_sink_rate"): + for par_name in ("bound_emission_pool_up", + "bound_emission_pool_lo", + "emission_sink_rate"): # Name of the corresponding set set_name = f"is_{par_name}" diff --git a/tutorial/westeros/westeros_emission_pools.ipynb b/tutorial/westeros/westeros_emission_pools.ipynb index a8a8a814f..663f94dba 100644 --- a/tutorial/westeros/westeros_emission_pools.ipynb +++ b/tutorial/westeros/westeros_emission_pools.ipynb @@ -254,7 +254,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## OPTIONAL: Add `bound_emission_pool`" + "## OPTIONAL: Add `bound_emission_pool_up`" ] }, { @@ -273,8 +273,7 @@ " 'value': [87000, 86000, 85000],\n", " 'unit': '???'\n", " })\n", - " scen.add_par('bound_emission_pool', df)\n", - " \n", + " scen.add_par('bound_emission_pool_up', df)\n", " # Remove bound_emission\n", " df = scen.par('bound_emission')\n", " scen.remove_par('bound_emission', df)\n", @@ -357,7 +356,7 @@ "# 710 78031.405954\n", "# 720 74315.624718\n", "\n", - "# WITH `bound_emission_pool' EMISS_POOL should have results:\n", + "# WITH `bound_emission_pool_up' EMISS_POOL should have results:\n", "# 700 87000\n", "# 710 85975.299326\n", "# 720 85000" From 4b69843dd4aeb6dab0155fdbb4268746da876001 Mon Sep 17 00:00:00 2001 From: Behnam Date: Wed, 15 Dec 2021 13:27:54 +0100 Subject: [PATCH 43/47] Change =G= to =E= in model_core for EMISS_POOL --- message_ix/model/MESSAGE/model_core.gms | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/message_ix/model/MESSAGE/model_core.gms b/message_ix/model/MESSAGE/model_core.gms index f4713c4ab..2ce04381a 100644 --- a/message_ix/model/MESSAGE/model_core.gms +++ b/message_ix/model/MESSAGE/model_core.gms @@ -1908,7 +1908,7 @@ EMISSION_CONSTRAINT(node,type_emission,type_tec,type_year)$is_bound_emission(nod *** EMISSION_POOL_EQUIVALENCE(node,emission,type_tec,year)$is_emission_sink_rate(node,emission,type_tec,year).. - EMISS_POOL(node,emission,type_tec,year) =G= + EMISS_POOL(node,emission,type_tec,year) =E= SUM(year_all2$( seq_period(year_all2,year) ), * emission pool from historical period if year == firstmodelyear historical_emission_pool(node,emission,type_tec,year_all2)$first_period(year) From e8b768a7082b1fae14f061e09e1d70a3310498c4 Mon Sep 17 00:00:00 2001 From: FRICKO Oliver Date: Mon, 13 Dec 2021 12:07:35 +0100 Subject: [PATCH 44/47] Reset of tutorial - clear_output --- .../westeros/westeros_emission_pools.ipynb | 196 ++---------------- 1 file changed, 23 insertions(+), 173 deletions(-) diff --git a/tutorial/westeros/westeros_emission_pools.ipynb b/tutorial/westeros/westeros_emission_pools.ipynb index 663f94dba..37b232f0a 100644 --- a/tutorial/westeros/westeros_emission_pools.ipynb +++ b/tutorial/westeros/westeros_emission_pools.ipynb @@ -15,22 +15,9 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "application/javascript": [ - "IPython.OutputArea.prototype._should_scroll = function(lines) { return false; }" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "import pandas as pd\n", "import ixmp\n", @@ -43,7 +30,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -52,7 +39,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -66,7 +53,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -85,7 +72,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -121,7 +108,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -138,7 +125,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -164,7 +151,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -181,7 +168,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -197,7 +184,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -224,7 +211,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -259,7 +246,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -296,7 +283,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -306,7 +293,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -315,20 +302,9 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "221792.71875" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "scen.var('OBJ')['lvl']" ] @@ -342,7 +318,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -364,144 +340,18 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
nodeemissiontype_tecyearlvlmrg
0WesterosCO2all70086254.7479760.0
1WesterosCO2all71083545.1152160.0
2WesterosCO2all72085000.0000000.0
\n", - "
" - ], - "text/plain": [ - " node emission type_tec year lvl mrg\n", - "0 Westeros CO2 all 700 86254.747976 0.0\n", - "1 Westeros CO2 all 710 83545.115216 0.0\n", - "2 Westeros CO2 all 720 85000.000000 0.0" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "scen.var('EMISS_POOL')" ] }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
nodetype_emissiontype_tecyearlvlmrg
0WesterosGHGall72033.0755720.0
\n", - "
" - ], - "text/plain": [ - " node type_emission type_tec year lvl mrg\n", - "0 Westeros GHG all 720 33.075572 0.0" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "scen.var('PRICE_EMISSION_POOL')" ] @@ -515,7 +365,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ From edf2c1bbf38823a997077ea7706bb5fbac318e1f Mon Sep 17 00:00:00 2001 From: FRICKO Oliver Date: Mon, 13 Dec 2021 13:38:33 +0100 Subject: [PATCH 45/47] Revise tests for carbon_pool adjustments --- message_ix/tests/test_emission_pool.py | 124 +++++++++++++++++++------ 1 file changed, 94 insertions(+), 30 deletions(-) diff --git a/message_ix/tests/test_emission_pool.py b/message_ix/tests/test_emission_pool.py index 0b4bf6602..578433cca 100644 --- a/message_ix/tests/test_emission_pool.py +++ b/message_ix/tests/test_emission_pool.py @@ -191,7 +191,7 @@ def test_tax_emission_pool_world(test_mp): pdt.assert_frame_equal(exp, obs, check_dtype=False) -def test_bound_emission_pool(test_mp): +def test_bound_emission_pool_up(test_mp): s = make_westeros(test_mp, quiet=True) prep_scenario(s, test_mp) @@ -206,8 +206,8 @@ def test_bound_emission_pool(test_mp): "unit": "???", } ) - s.add_par("bound_emission_pool", df) - s.commit("bound_emission_pool added") + s.add_par("bound_emission_pool_up", df) + s.commit("bound_emission_pool_up added") s.solve() @@ -242,7 +242,7 @@ def test_bound_emission_pool(test_mp): pdt.assert_frame_equal(exp, obs, check_dtype=False) -def test_bound_emission_pool_removal(test_mp): +def test_bound_emission_pool_lo(test_mp): s = make_westeros(test_mp, quiet=True) prep_scenario(s, test_mp) @@ -257,31 +257,95 @@ def test_bound_emission_pool_removal(test_mp): "unit": "???", } ) - s.add_par("bound_emission_pool", df) - s.commit("bound_emission_pool added") + s.add_par("bound_emission_pool_up", df) + + df = pd.DataFrame( + { + "node": "Westeros", + "type_emission": "GHG", + "type_tec": "all", + "year": [710], + "value": [84000], + "unit": "???", + } + ) + s.add_par("bound_emission_pool_lo", df) + + s.commit("bound_emission_pool_lo and _up added") + + s.solve() + + exp = pd.DataFrame( + { + "node": "Westeros", + "emission": "CO2", + "type_tec": "all", + "year": [700, 710, 720], + "lvl": [86254.74797636835, 84000.0, 85000.0], + "mrg": 0.0, + } + ) + + obs = s.var("EMISS_POOL") + + pdt.assert_frame_equal(exp, obs, check_dtype=False) + + exp = pd.DataFrame( + { + "node": "Westeros", + "type_emission": "GHG", + "type_tec": "all", + "year": [720], + "lvl": [33.075572], + "mrg": 0.0, + } + ) + + obs = s.var("PRICE_EMISSION_POOL") + + pdt.assert_frame_equal(exp, obs, check_dtype=False) + + +def test_bound_emission_pool_up_removal(test_mp): + s = make_westeros(test_mp, quiet=True) + prep_scenario(s, test_mp) + + s.check_out() + df = pd.DataFrame( + { + "node": "Westeros", + "type_emission": "GHG", + "type_tec": "all", + "year": [700, 710, 720], + "value": [87000, 86000, 85000], + "unit": "???", + } + ) + s.add_par("bound_emission_pool_up", df) + s.commit("bound_emission_pool_up added") # Ensure that bound has been added - obs = s.par("bound_emission_pool") + obs = s.par("bound_emission_pool_up") pdt.assert_frame_equal(df, obs, check_dtype=False) s.solve() # Ensure that is_ set for bound has been added upon solving exp = df.drop(["value", "unit"], axis=1) - obs = s.set("is_bound_emission_pool") + obs = s.set("is_bound_emission_pool_up") pdt.assert_frame_equal(exp, obs, check_dtype=False) # Esnure that is_ set is removed when removing parameter s.remove_solution() s.check_out() - s.remove_par("bound_emission_pool", df) + s.remove_par("bound_emission_pool_up", df) s.commit("bound_emission_poll removed") - obs = s.set("is_bound_emission_pool") + obs = s.set("is_bound_emission_pool_up") assert obs.empty is True -def test_bound_emission_pool_modification_inc_yrs(test_mp): +def test_bound_emission_pool_up_modification_inc_yrs(test_mp): s = make_westeros(test_mp, quiet=True) prep_scenario(s, test_mp) @@ -296,18 +360,18 @@ def test_bound_emission_pool_modification_inc_yrs(test_mp): "unit": "???", } ) - s.add_par("bound_emission_pool", df) - s.commit("bound_emission_pool added") + s.add_par("bound_emission_pool_up", df) + s.commit("bound_emission_pool_up added") # Ensure that bound has been added - obs = s.par("bound_emission_pool") + obs = s.par("bound_emission_pool_up") pdt.assert_frame_equal(df, obs, check_dtype=False) s.solve() # Ensure that is_ set for bound has been added upon solving exp = df.drop(["value", "unit"], axis=1) - obs = s.set("is_bound_emission_pool") + obs = s.set("is_bound_emission_pool_up") pdt.assert_frame_equal(exp, obs, check_dtype=False) # Now check that when the dataframe is extended, if the "is_" set @@ -324,22 +388,22 @@ def test_bound_emission_pool_modification_inc_yrs(test_mp): "unit": "???", } ) - s.add_par("bound_emission_pool", df) - s.commit("bound_emission_pool added") + s.add_par("bound_emission_pool_up", df) + s.commit("bound_emission_pool_up added") # Ensure that bound has been added - obs = s.par("bound_emission_pool") + obs = s.par("bound_emission_pool_up") pdt.assert_frame_equal(df, obs, check_dtype=False) s.solve() # Ensure that is_ set for bound has been added upon solving exp = df.drop(["value", "unit"], axis=1) - obs = s.set("is_bound_emission_pool") + obs = s.set("is_bound_emission_pool_up") pdt.assert_frame_equal(exp, obs, check_dtype=False) -def test_bound_emission_pool_modification_red_yrs(test_mp): +def test_bound_emission_pool_up_modification_red_yrs(test_mp): s = make_westeros(test_mp, quiet=True) prep_scenario(s, test_mp) @@ -354,18 +418,18 @@ def test_bound_emission_pool_modification_red_yrs(test_mp): "unit": "???", } ) - s.add_par("bound_emission_pool", df) - s.commit("bound_emission_pool added") + s.add_par("bound_emission_pool_up", df) + s.commit("bound_emission_pool_up added") # Ensure that bound has been added - obs = s.par("bound_emission_pool") + obs = s.par("bound_emission_pool_up") pdt.assert_frame_equal(df, obs, check_dtype=False) s.solve() # Ensure that is_ set for bound has been added upon solving exp = df.drop(["value", "unit"], axis=1) - obs = s.set("is_bound_emission_pool") + obs = s.set("is_bound_emission_pool_up") pdt.assert_frame_equal(exp, obs, check_dtype=False) # Now check that when the dataframe is extended, if the "is_" set @@ -374,8 +438,8 @@ def test_bound_emission_pool_modification_red_yrs(test_mp): s.check_out() # Remove existing - df = s.par("bound_emission_pool") - s.remove_par("bound_emission_pool", df) + df = s.par("bound_emission_pool_up") + s.remove_par("bound_emission_pool_up", df) df = pd.DataFrame( { @@ -387,16 +451,16 @@ def test_bound_emission_pool_modification_red_yrs(test_mp): "unit": "???", } ) - s.add_par("bound_emission_pool", df) - s.commit("bound_emission_pool added") + s.add_par("bound_emission_pool_up", df) + s.commit("bound_emission_pool_up added") # Ensure that bound has been added - obs = s.par("bound_emission_pool") + obs = s.par("bound_emission_pool_up") pdt.assert_frame_equal(df, obs, check_dtype=False) s.solve() # Ensure that is_ set for bound has been added upon solving exp = df.drop(["value", "unit"], axis=1) - obs = s.set("is_bound_emission_pool") + obs = s.set("is_bound_emission_pool_up") pdt.assert_frame_equal(exp, obs, check_dtype=False) From 26a43bfcbe63acbd45781f5e12048f017183b6b1 Mon Sep 17 00:00:00 2001 From: FRICKO Oliver Date: Tue, 21 Dec 2021 08:55:44 +0100 Subject: [PATCH 46/47] Apply black formatting --- message_ix/models.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/message_ix/models.py b/message_ix/models.py index 535d56ae2..1d7276fe6 100644 --- a/message_ix/models.py +++ b/message_ix/models.py @@ -166,7 +166,7 @@ def item(ix_type, expr): ), "bound_emission_pool_lo": dict( ix_type="par", idx_sets=["node", "type_emission", "type_tec", "year"] - ), + ), "bound_extraction_up": item("par", "n c g y"), "bound_new_capacity_lo": item("par", "nl t yv"), "bound_new_capacity_up": item("par", "nl t yv"), @@ -434,9 +434,11 @@ def enforce(scenario): # handled in JDBCBackend. For the moment, this code does not backstop that # behaviour. # TODO Extend to handle all masks, e.g. for new backends. - for par_name in ("bound_emission_pool_up", - "bound_emission_pool_lo", - "emission_sink_rate"): + for par_name in ( + "bound_emission_pool_up", + "bound_emission_pool_lo", + "emission_sink_rate", + ): # Name of the corresponding set set_name = f"is_{par_name}" From c7016ad4abfe62f9074f39f96e0f800d62782b6b Mon Sep 17 00:00:00 2001 From: FRICKO Oliver Date: Tue, 21 Dec 2021 09:05:18 +0100 Subject: [PATCH 47/47] Update tests to pass --- message_ix/tests/test_emission_pool.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/message_ix/tests/test_emission_pool.py b/message_ix/tests/test_emission_pool.py index 578433cca..27791dd93 100644 --- a/message_ix/tests/test_emission_pool.py +++ b/message_ix/tests/test_emission_pool.py @@ -296,7 +296,7 @@ def test_bound_emission_pool_lo(test_mp): "type_emission": "GHG", "type_tec": "all", "year": [720], - "lvl": [33.075572], + "lvl": [52.80722057294146], "mrg": 0.0, } ) @@ -335,12 +335,15 @@ def test_bound_emission_pool_up_removal(test_mp): obs = s.set("is_bound_emission_pool_up") pdt.assert_frame_equal(exp, obs, check_dtype=False) - # Esnure that is_ set is removed when removing parameter + # Ensure that is_ set is removed when removing parameter s.remove_solution() s.check_out() s.remove_par("bound_emission_pool_up", df) s.commit("bound_emission_poll removed") + # Solve + s.solve() + obs = s.set("is_bound_emission_pool_up") assert obs.empty is True