diff --git a/doc/_static/usage_figures/10.1016-j.est.2022.104587.JPG b/doc/_static/usage_figures/10.1016-j.est.2022.104587.JPG new file mode 100644 index 000000000..fda415dfd Binary files /dev/null and b/doc/_static/usage_figures/10.1016-j.est.2022.104587.JPG differ diff --git a/doc/references.bib b/doc/references.bib index eaa4c9d5c..e325fc043 100644 --- a/doc/references.bib +++ b/doc/references.bib @@ -137,3 +137,17 @@ @article{Messner2000 abstract = {MESSAGE-MACRO is the result of linking a macroeconomic model with a detailed energy supply model. The purpose of the linkage is to consistently reflect the influence of energy supply costs as calculated by the energy supply model in the optimal mix of production factors included in the macroeconomic model. In this article, we describe an automated link of two independently running models. The advantages of this set-up over a single, fully integrated model are two-fold: First, it is more flexible, leaving the constituent models intact for independent runs, thus making further model development an easier task. Second, the decomposed model solution benefits numerically from having the most non-linearities concentrated in the smaller of two modules. The emphasis of the paper is on methodology, but we also include an example demonstrating the feedback mechanisms of MESSAGE-MACRO by applying it to two global economic-energy-environment scenarios. The two scenarios are a reference scenario and a scenario that limits the global atmospheric carbon concentration to 550 ppmv. The scenarios are compared in terms of GDP, energy supply and demand, and energy prices.}, author = {Messner, S. and Schrattenholzer, L.} } + +@article{Zakeri2022, +title = {Role of energy storage in energy and water security in Central Asia}, +journal = {Journal of Energy Storage}, +volume = {50}, +pages = {104587}, +year = {2022}, +issn = {2352-152X}, +doi = {https://doi.org/10.1016/j.est.2022.104587}, +url = {https://www.sciencedirect.com/science/article/pii/S2352152X2200603X}, +author = {Behnam Zakeri and Julian David Hunt and Murodbek Laldjebaev and Volker Krey and Adriano Vinca and Simon Parkinson and Keywan Riahi}, +keywords = {Energy storage, Seasonal pumped hydropower storage, Water management, Renewable energy systems, Energy policy, Electricity storage, Energy model}, +abstract = {Central Asia has faced major energy and water security challenges. Technically, water from the Pamir and Tian Shan Mountain ranges could be sufficient to meet the needs of the countries in the region, if there was no temporal mismatch between the availability of water for irrigation and electricity generation. While water is required for agriculture in downstream countries during the summer, demand for hydro electricity generation is mainly in the wintertime in upstream countries. With the aid of the open-source MESSAGEix energy systems optimization modelling framework, we study a renewable energy transition in the region through to 2050, considering innovative long duration water and energy storage solutions for optimal management of water and energy resources in different seasons. The modelling approach demonstrates that the proposed "dual water and energy storage scheme", with two different hydrological cycles for up- and down-stream regions, can guarantee enough water for energy generation in upstream countries in winter while ensuring water availability for irrigation downstream in summer. This scheme is economically feasible and, with further detailed analyses and geo-political considerations, it can serve to improve energy security and water resource management, towards achieving sustainable development goals in Central Asia.} +} diff --git a/doc/usage.rst b/doc/usage.rst index b901a6f29..4c47e54eb 100644 --- a/doc/usage.rst +++ b/doc/usage.rst @@ -23,6 +23,21 @@ Publications The following is a selection of academic publications in which |MESSAGEix| was used to carry out energy systems research. For each, the spatial scope/resolution, keywords and specific usage of |MESSAGEix| are described. +Role of energy storage in energy and water security in Central Asia +----------------------------------------------------------------------------------- +.. figure:: _static/usage_figures/10.1016-j.est.2022.104587.JPG + :width: 250px + :align: right + +:cite:ct:`Zakeri2022` + +- **Spatial**: Regional (Central Asia), multi-country including Kazakhstan, Kyrgyzstan, Tajikistan, Turkmenistan, and Uzbekistan +- **Keywords**: Energy storage, seasonal pumped hydropower storage, water management, renewable energy systems, energy policy, electricity storage, energy model +- **Usage**: Model the energy-water system of Central Asia with 12 sub-annual time slices and analyze the role of energy and water storage solutions. +- **Data and code**: Data and scripts for building the model are openly available on `Github `__ + +Central Asia has faced major energy and water security challenges. Technic… `Read more → `__ + Climate mitigation scenarios with persistent COVID-19-related energy demand changes ----------------------------------------------------------------------------------- .. figure:: _static/usage_figures/41560_2021_904.webp diff --git a/message_ix/testing/__init__.py b/message_ix/testing/__init__.py index c1e869d19..028bb4d25 100644 --- a/message_ix/testing/__init__.py +++ b/message_ix/testing/__init__.py @@ -675,7 +675,7 @@ def make_subannual( scen.add_set("technology", list(tec_dict.keys())) # Add "time" and "duration_time" to the model - for (h, dur, tmp_lvl, parent) in time_steps: + for h, dur, tmp_lvl, parent in time_steps: scen.add_set("time", h) scen.add_set("time", parent) scen.add_set("lvl_temporal", tmp_lvl) diff --git a/message_ix/tests/test_equation_NEW_CAPACITY_CONTRAINT.py b/message_ix/tests/test_equation_NEW_CAPACITY_CONTRAINT.py index d8ad22180..3b9ccdb51 100644 --- a/message_ix/tests/test_equation_NEW_CAPACITY_CONTRAINT.py +++ b/message_ix/tests/test_equation_NEW_CAPACITY_CONTRAINT.py @@ -41,7 +41,6 @@ def test_NEW_CAPACITY_UP(test_mp, model_horizon): # Make changes with s.transact("prepare for test"): - # Add tax_emission s.add_par("tax_emission", tax_emission) diff --git a/message_ix/tests/test_feature_bound_activity_shares.py b/message_ix/tests/test_feature_bound_activity_shares.py index b9e0790ac..a892b3375 100644 --- a/message_ix/tests/test_feature_bound_activity_shares.py +++ b/message_ix/tests/test_feature_bound_activity_shares.py @@ -114,6 +114,7 @@ def test_commodity_share_up(message_test_mp): transport_from_san-diego (original: 550). Expected outcome: some increase of transport_from_san-diego with some decrease of production in seattle. """ + # data for share bound def calc_share(s): a = s.var( diff --git a/message_ix/tests/test_feature_duration_time.py b/message_ix/tests/test_feature_duration_time.py index ab1352122..c8824a7e5 100644 --- a/message_ix/tests/test_feature_duration_time.py +++ b/message_ix/tests/test_feature_duration_time.py @@ -116,7 +116,7 @@ def model_generator( time_pairs = zip(times_in, times_out) # Configuring data for "time_origin" and "time" in "input" - for (h_in, h_act) in time_pairs: + for h_in, h_act in time_pairs: # "input" inp = com_dict[tec]["input"] if inp: @@ -149,6 +149,7 @@ def model_generator( # In these tests "demand" is defined in different time slices and one power plant # to meet demand, which receives fuel from a supply technology. + # Testing one temporal level ("season") and different number of time slices def test_season(test_mp, n_time=[4, 12, 50]): comment = "season" diff --git a/message_ix/tests/test_feature_storage.py b/message_ix/tests/test_feature_storage.py index cca6ceb32..077c49da3 100644 --- a/message_ix/tests/test_feature_storage.py +++ b/message_ix/tests/test_feature_storage.py @@ -123,7 +123,6 @@ def add_storage_data(scen, time_order): # Main function for building a model with storage and testing the functionality def storage_setup(test_mp, time_duration, comment): - # First, building a simple model and adding seasonality scen = Scenario(test_mp, "no_storage", "standard", version="new") model_setup(scen, [2020]) diff --git a/message_ix/tests/tools/test_add_year.py b/message_ix/tests/tools/test_add_year.py index 07f62e956..cee0e863c 100644 --- a/message_ix/tests/tools/test_add_year.py +++ b/message_ix/tests/tools/test_add_year.py @@ -20,7 +20,7 @@ def base_scen_mp(test_mp): scen.add_set("mode", "mode") output_specs = ["node", "comm", "level", "year", "year"] - for (yr, value) in data.items(): + for yr, value in data.items(): scen.add_par("demand", ["node", "comm", "level", yr, "year"], 1, "GWa") scen.add_par("technical_lifetime", ["node", "tec", yr], 10, "y") tec_specs = ["node", "tec", yr, yr, "mode"] diff --git a/message_ix/tools/add_year/__init__.py b/message_ix/tools/add_year/__init__.py index 85e3f4a2a..fe9d79ba6 100644 --- a/message_ix/tools/add_year/__init__.py +++ b/message_ix/tools/add_year/__init__.py @@ -815,7 +815,6 @@ def f(x, i): j = horizon_new.index(yr) if yr - horizon_new[j - 1] >= horizon_new[j - 1] - horizon_new[j - 2]: - df2[yr].loc[ (pd.isna(df2[year_pre].shift(+1))) & (~pd.isna(df2[year_pp].shift(+1))) @@ -937,7 +936,6 @@ def f(x, i): # ------------------------------------------------------------------------- # Forth: final masking based on technical lifetime if tec_list and not df_dur.empty: - df3 = ( df2.loc[df2.index.get_level_values("technology").isin(tec_list), :] .copy() diff --git a/pyproject.toml b/pyproject.toml index 955afd8fc..c087598c2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -121,3 +121,10 @@ markers = [ "nightly: Slow-running nightly tests of particular scenarios.", "rmessageix: test of the message_ix R interface.", ] + +[tool.coverage.run] +omit = [ + "message_ix/model/*", + "message_ix/tests/test_nightly.py", + "message_ix/testing/nightly.py", +] diff --git a/setup.cfg b/setup.cfg index c9e67f176..2cf3014ca 100644 --- a/setup.cfg +++ b/setup.cfg @@ -68,11 +68,5 @@ tests = console_scripts = message-ix = message_ix.cli:main -[codecov.run] -omit = - message_ix/model/* - message_ix/tests/test_nightly.py - message_ix/testing/nightly.py - [flake8] max-line-length = 88