diff --git a/message_ix/tests/test_tutorials.py b/message_ix/tests/test_tutorials.py
index 98b752215..7774273c5 100644
--- a/message_ix/tests/test_tutorials.py
+++ b/message_ix/tests/test_tutorials.py
@@ -1,4 +1,5 @@
import sys
+from shutil import copyfile
import numpy as np
import pytest
@@ -23,6 +24,8 @@
[("solve-objective-value", 369297.75)],
{},
),
+ (("westeros", "westeros_baseline_using_xlsx_import_part1"), [], {}),
+ (("westeros", "westeros_baseline_using_xlsx_import_part2"), [], {}),
(("westeros", "westeros_emissions_bounds"), [], {}),
(("westeros", "westeros_emissions_taxes"), [], {}),
(("westeros", "westeros_firm_capacity"), [], {}),
@@ -49,6 +52,15 @@
# Short, readable IDs for the tests
ids = [arg[0][-1] for arg in tutorials]
+# List of data files required to run tutorials
+data_files = [
+ "westeroes_baseline_demand.xlsx",
+ "westeroes_baseline_technology_basic.xlsx",
+ "westeroes_baseline_technology_constraint.xlsx",
+ "westeroes_baseline_technology_economic.xlsx",
+ "westeroes_baseline_technology_historic.xlsx",
+]
+
@pytest.fixture
def nb_path(request, tutorial_path):
@@ -76,6 +88,12 @@ def test_tutorial(nb_path, cell_values, run_args, tmp_path, tmp_env):
[str(nb_path.parent), tmp_env.get("PYTHONPATH", "")]
)
+ # Copy necessary data files to tmp_path
+ print(nb_path)
+ if "westeros_baseline_using_xlsx_import_part2" in nb_path.parts[-1]:
+ for fil in data_files:
+ copyfile(nb_path.parent / fil, tmp_path / fil)
+
# The notebook can be run without errors
nb, errors = run_notebook(nb_path, tmp_path, tmp_env, **run_args)
assert errors == []
diff --git a/tutorial/README.rst b/tutorial/README.rst
index 7c5093754..3759a1be7 100644
--- a/tutorial/README.rst
+++ b/tutorial/README.rst
@@ -110,6 +110,10 @@ uses it to illustrate a range of framework features.
#. Add-on technologies: Add the possibility of co-generation for the coal
power plant, by allowing it to produce heat via a passout-turbine
(:tut:`westeros/westeros_addon_technologies.ipynb`).
+ #. Build the baseline scenario using data stored in xlsx files to populate sets and
+ parameters (:tut:`westeros_baseline_using_xlsx_import_part1.ipynb`).
+ #. Build the baseline scenario using data stored in mutliple xlsx files to populate
+ sets and parameters (:tut:`westeros_baseline_using_xlsx_import_part2.ipynb`).
#. After the MESSAGE model has solved, use the :mod:`.message_ix.reporting`
module to ‘report’ results, e.g. do post-processing, plotting, and other
diff --git a/tutorial/westeros/_static/westeroes_baseline_xlsx_workflow.pptx b/tutorial/westeros/_static/westeroes_baseline_xlsx_workflow.pptx
new file mode 100644
index 000000000..a81ed7bac
Binary files /dev/null and b/tutorial/westeros/_static/westeroes_baseline_xlsx_workflow.pptx differ
diff --git a/tutorial/westeros/_static/westeroes_baseline_xlsx_workflow_part1.jpg b/tutorial/westeros/_static/westeroes_baseline_xlsx_workflow_part1.jpg
new file mode 100644
index 000000000..7311d169b
Binary files /dev/null and b/tutorial/westeros/_static/westeroes_baseline_xlsx_workflow_part1.jpg differ
diff --git a/tutorial/westeros/_static/westeroes_baseline_xlsx_workflow_part2.jpg b/tutorial/westeros/_static/westeroes_baseline_xlsx_workflow_part2.jpg
new file mode 100644
index 000000000..b960d0d1e
Binary files /dev/null and b/tutorial/westeros/_static/westeroes_baseline_xlsx_workflow_part2.jpg differ
diff --git a/tutorial/westeros/westeroes_baseline_demand.xlsx b/tutorial/westeros/westeroes_baseline_demand.xlsx
new file mode 100644
index 000000000..b182b55c2
Binary files /dev/null and b/tutorial/westeros/westeroes_baseline_demand.xlsx differ
diff --git a/tutorial/westeros/westeroes_baseline_technology_basic.xlsx b/tutorial/westeros/westeroes_baseline_technology_basic.xlsx
new file mode 100644
index 000000000..d54f6ee49
Binary files /dev/null and b/tutorial/westeros/westeroes_baseline_technology_basic.xlsx differ
diff --git a/tutorial/westeros/westeroes_baseline_technology_constraint.xlsx b/tutorial/westeros/westeroes_baseline_technology_constraint.xlsx
new file mode 100644
index 000000000..10e3dee68
Binary files /dev/null and b/tutorial/westeros/westeroes_baseline_technology_constraint.xlsx differ
diff --git a/tutorial/westeros/westeroes_baseline_technology_economic.xlsx b/tutorial/westeros/westeroes_baseline_technology_economic.xlsx
new file mode 100644
index 000000000..1ffa52f88
Binary files /dev/null and b/tutorial/westeros/westeroes_baseline_technology_economic.xlsx differ
diff --git a/tutorial/westeros/westeroes_baseline_technology_historic.xlsx b/tutorial/westeros/westeroes_baseline_technology_historic.xlsx
new file mode 100644
index 000000000..3fd434053
Binary files /dev/null and b/tutorial/westeros/westeroes_baseline_technology_historic.xlsx differ
diff --git a/tutorial/westeros/westeros_baseline_using_xlsx_import_part1.ipynb b/tutorial/westeros/westeros_baseline_using_xlsx_import_part1.ipynb
new file mode 100644
index 000000000..82d80206d
--- /dev/null
+++ b/tutorial/westeros/westeros_baseline_using_xlsx_import_part1.ipynb
@@ -0,0 +1,255 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "# Westeros Tutorial Part 4a - Building a scenario by importing data from Excel (I)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "## Scope of this tutorial\n",
+ "\n",
+ "This tutorial explains how the Westeros Baseline scenario can be built using data imported from Excel (.xlsx) files. The figure below compares the workflows of the original westeroes tutorial, where data was added using the [add_par()](https://docs.messageix.org/projects/ixmp/en/stable/api.html?highlight=add_set()#ixmp.Scenario.add_par) and [add_set()](https://docs.messageix.org/projects/ixmp/en/stable/api.html?highlight=add_set()#ixmp.Scenario.add_set) functions. The same scenario can also be created by importing data from an Excel file, using [ixmp.Scenario.read_excel()](https://docs.messageix.org/projects/ixmp/en/latest/api.html#ixmp.Scenario.read_excel) as shown in the figure below.\n",
+ "\n",
+ "
\n",
+ "\n",
+ "We also demonstrate how to export data to an Excel file. In the first part of this tutorial we are load the scenario which we created in `westeros_baseline.ipynb`, and export the scenario data to an Excel file.\n",
+ "\n",
+ "In the sceond part, we import the data from the Excel file to create a new scenario.\n",
+ "\n",
+ "### Requirements\n",
+ "\n",
+ "Please add some notes for the requirements of running this tutorial\n",
+ "\n",
+ "\n",
+ "\n",
+ "### Online documentation\n",
+ "\n",
+ "The documentation of the MESSAGEix framework is available at [https://docs.messageix.org](https://docs.messageix.org)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "Similar to other tutorials, we start by importing all the packages we need."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import ixmp\n",
+ "import message_ix\n",
+ "\n",
+ "%matplotlib inline"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Loading Modeling platform\n",
+ "mp = ixmp.Platform()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Step 1. Loading the Westeros baseline scenario"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "base = message_ix.Scenario(mp, model='Westeros Electrified', scenario='baseline')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Step 2. Export the data to an Excel file\n",
+ "We export all the scenario data (sets and parameters) to a single Excel file called `westeros_baseline_data.xlsx`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data_file = 'westeros_baseline_data.xlsx'\n",
+ "base.to_excel(data_file)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "You can open the created Excel file on your machine and navigate through the Excel sheets and make yourself familiar with the format that the data have been stored in the file."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Step 3. Create a new scenario"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Creating a new, empty scenario\n",
+ "scenario = message_ix.Scenario(mp, model='Westeros Electrified', \n",
+ " scenario='baseline_xlsx', version='new')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "## Step 4: Importing data from Excel"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "source": [
+ "Instead of using the `message_ix.Scenario.add_set()` and `add_par()` for adding data to a MESSAGEix parameter, we import data from an xlsx file. The arguments `add_units` is set to `True`, so that any units which have not yet been specified in the modeling platform can be defined automatically."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "scenario.read_excel(data_file, add_units=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "## Time to Solve the Model"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "scenario.set_as_default()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "scenario.solve()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "jupyter": {
+ "name": "solve-objective-value"
+ },
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "scenario.var('OBJ')['lvl']"
+ ]
+ }
+ ],
+ "metadata": {
+ "anaconda-cloud": {},
+ "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.8.5"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/tutorial/westeros/westeros_baseline_using_xlsx_import_part2.ipynb b/tutorial/westeros/westeros_baseline_using_xlsx_import_part2.ipynb
new file mode 100644
index 000000000..19b896a60
--- /dev/null
+++ b/tutorial/westeros/westeros_baseline_using_xlsx_import_part2.ipynb
@@ -0,0 +1,655 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "# Westeros Tutorial Part 4a - Importing scenario data from Excel (II)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "## Scope of this tutorial\n",
+ "\n",
+ "In the first part of this tutorial, `Westeros Tutorial Part 4a (Part I)`, we explained how data of the Westeros Baseline scenario can be exported to an Excel (.xlsx) file using [ixmp.Scenario.to_excel()](https://docs.messageix.org/projects/ixmp/en/latest/api.html#ixmp.Scenario.to_excel); and how the data can be imported from Excel to build a new scenario using [ixmp.Scenario.read_excel()](https://docs.messageix.org/projects/ixmp/en/latest/api.html#ixmp.Scenario.read_excel). This tutorial shows a more detailed workflow for building a new scenario from data stored in one or a few Excel files. This can be useful specifically for the following applications:\n",
+ "\n",
+ "- Migrating a model/scenario from another modeling tool to MESSAGEix\n",
+ "- Modifying the input data of a MESSAGEix scenario using Excel\n",
+ "\n",
+ "\n",
+ "To do this, we are again going to build the Westeros Baseline, but this time with importing data from multiple Excel files (see figure below), instead of one single file. This tutorial specifically targets users looking to build larger and more complex models using the Excel import functionalities. The advantage of using multiple Excel files, especially for large data sets, is to divide the underlying workflow into several independent subsections. This means the scripts related to creating the Excel files and importing such data to MESSAGEix can be grouped into certain model sets and parameters, e.g., one data file for cost parameters and another file for technical parameters etc. Therefore, the data import process will be shorter, and updates of data can be performed more easily in the future. \n",
+ "\n",
+ "
\n",
+ "\n",
+ "The first part of this tutorial will create a scenario and basic parameters will be added including the modeling time-horizon and the discount rate. This code is a repetition of that used in the tutorial `westeros_baseline.ipynb`, which will be referred to as the \"original\" scenario throughout the remainder of this tutorial.\n",
+ "\n",
+ "The sceond part will then import various parameters from a few Excel files, adding technologies, demand and constraints to the model. The user can choose how to distribute the data across various excel files. We show one method of doing this distribution to outline a possible approach on how to structure the import methods if used for loading large amounts of data into scenarios, as well to demonstarte the required format of data in the excel files.\n",
+ "\n",
+ "#### Notice:\n",
+ "The MESSAGEix modeling framework includes powerful tools for data handling and storage. As such, we don not recommend using Excel files for storing and processing of scenario data. The methods introduced here may help some new users to import their model data and build a new model in MESSAGEix. But for most users, python and R interfaces are much more flexible for working with MESSAGEix scenario.\n",
+ "\n",
+ "### Requirements for running this tutorial\n",
+ "\n",
+ "[Please add here some notes on what they need to do before running this tutorial]\n",
+ "\n",
+ "\n",
+ "### Online documentation\n",
+ "\n",
+ "The documentation of the MESSAGEix framework is available at [https://docs.messageix.org](https://docs.messageix.org)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Step 1. Setting up the scenario"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "Similar to other tutorials, we start by importing all the packages we need."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import ixmp\n",
+ "import message_ix\n",
+ "\n",
+ "%matplotlib inline"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Loading Modeling platform\n",
+ "mp = ixmp.Platform()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Creating a new, empty scenario\n",
+ "scenario = message_ix.Scenario(mp, model='Westeros Electrified', \n",
+ " scenario='baseline_xlsx', version='new')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "## Model Structure\n",
+ "\n",
+ "As in the original tuorial, basic characteristics of the model, including model years, location, and the energy system structure are defined. We also definie the interest rate."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Defining historical and model (optimization) years\n",
+ "history = [690]\n",
+ "model_horizon = [700, 710, 720]\n",
+ "scenario.add_horizon(\n",
+ " year=history + model_horizon,\n",
+ " firstmodelyear=model_horizon[0]\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Defining a spatial level and adding a node to it\n",
+ "node = 'Westeros'\n",
+ "scenario.add_spatial_sets({'country': node})"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Contrary to the original tutorial for building the Westeros model, we only define commodities and levels here. If additional `commodity` or `level` types are required later on, these can also be defined in the Excel files, and be uploaded with technologoy data using the excel files. Either method is fine.\n",
+ "Note that we populated the set `technology` and `mode` in the original tutorial. We will address these in the second half of this tutorial."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Adding elements to MESSAGEix sets\n",
+ "scenario.add_set(\"commodity\", [\"electricity\", \"light\"])\n",
+ "scenario.add_set(\"level\", [\"secondary\", \"final\", \"useful\"])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Adding interest rate of 5% per model year\n",
+ "scenario.add_par(\"interestrate\", model_horizon, value=0.05, unit='-')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Note that the data has not yet been commited. This is because at a minimum, the set technology needs to be defined otherwise an error message will be raised when commiting the scenario. Hence, we will continue in this tutorial by adding data, step-by-step, in the process of which commits are automatically made."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "## Step 2: Importing data from Excel\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "### 2.1 Supply and Demand (or Balancing Commodities)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "source": [
+ "Instead of using the `message_ix.Scenario.add_par()` for adding data to a MESSAGEix parameter, we import data from a xlsx file. The arguments `add_units` has been set to `True`, so that any units which have not yet been specified in the modeling platform will be defined automatically."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "scenario.read_excel(\"westeroes_baseline_demand.xlsx\", add_units=True, commit_steps=False)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Open the above indicated xlsx (\"westeroes_baseline_demand.xlsx\") file and browse its contents. You will find that it includes two sheets. A sheet `demand` which contains the based on the index structure of the parameters `demand`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(scenario.idx_names('demand'))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "In addition, numerical values have been added under the index-name `value` and the units have been specified under the index-name `unit`. These two index names are used for adding numerical values and units across all parameters."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 2.2 Adding technologies\n",
+ "The following sheets are distinguished in the data input file for the next step (\"westeroes_baseline_technology_basic.xlsx\"), which adds a basic configuration for technologies.\n",
+ "```\n",
+ "a. mode\n",
+ "b. technology\n",
+ "c. capacity_factor\n",
+ "d. input\n",
+ "e. output\n",
+ "f. technical_lifetime\n",
+ "g. ix_type_mapping\n",
+ "```\n",
+ "The naming convention of the sheets is analogue to the set or parameter to which the data contained within refers to. The exception is the last sheet (\"ix_type_mapping\"), which is used by the importer to distinguish which sheets are populate sets or parameters. This is important as first sets will need to be populated, to allow the import of parameters. The sets must include all unique entries in the parameters, otherwise if data in the sheet `capacity_factor` is defined for a technology which is not listed in the sheet `technology`, an error will be raised."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "scenario.read_excel(\"westeroes_baseline_technology_basic.xlsx\", add_units=True, commit_steps=False)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "In order to view which technologies we have added, we can do the following:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "scenario.set('technology')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can also look at the specific parameters by:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "scenario.par('capacity_factor')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "### 2.3 Technological Diffusion and Contraction\n",
+ "As we have already undertaken an initial definition of technologies, and will now proceed to add additional parameters for already defined technologies, the input data file (\"westeroes_baseline_technology_constraint.xlsx\") does not contain and sheets relating to sets."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "scenario.read_excel(\"westeroes_baseline_technology_constraint.xlsx\", add_units=True, commit_steps=False)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "### 2.4 Defining an Energy Mix (Model Calibration)\n",
+ "In this part, we import data of the historical years."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "scenario.read_excel(\"westeroes_baseline_technology_historic.xlsx\", add_units=True, commit_steps=False)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "### 2.5 Investment, Fixed O&M and Varaible O&M Costs\n",
+ "Here, we import the cost data from a separate file."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "scenario.read_excel(\"westeroes_baseline_technology_economic.xlsx\", add_units=True, commit_steps=False)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "## Time to Solve the Model"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "scenario.set_as_default()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "scenario.solve()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "jupyter": {
+ "name": "solve-objective-value"
+ },
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "scenario.var('OBJ')['lvl']"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "## Plotting Results\n",
+ "\n",
+ "Analyzing the results of a scenario after it is solved is called **reporting**.\n",
+ "MESSAGE*ix* includes flexible and customizable message_ix/tutorial for reporting, but here we wish to focus on the results of our example scenario.\n",
+ "We use some custom code to set up some simple plots:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Create a Reporter object to describe and carry out reporting\n",
+ "# calculations and operations (like plotting) based on `scenario`\n",
+ "from message_ix.reporting import Reporter\n",
+ "\n",
+ "rep = Reporter.from_scenario(scenario)\n",
+ "\n",
+ "# Add keys like \"plot activity\" to describe reporting operations.\n",
+ "# See tutorial/utils/plotting.py\n",
+ "from message_ix.util.tutorial import prepare_plots\n",
+ "\n",
+ "prepare_plots(rep)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "Now the object `rep` is ready to generate several plots.\n",
+ "\n",
+ "(For a detailed introduction to how the `Reporter` works, see `westeros_report.ipynb`.)\n",
+ "\n",
+ "### Activity\n",
+ "\n",
+ "How much energy is generated in each time period from the different potential sources?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Only show a subset of technologies in the follow plots;\n",
+ "# e.g. exclude \"bulb\" and \"grid\"\n",
+ "rep.set_filters(t=[\"coal_ppl\", \"wind_ppl\"])\n",
+ "\n",
+ "# Trigger the calculation and plotting\n",
+ "rep.get(\"plot activity\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "### Capacity\n",
+ "\n",
+ "How much capacity of each plant is installed in each period?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Create a different plot. The same filters are still active.\n",
+ "rep.get(\"plot capacity\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "### Electricity Price\n",
+ "\n",
+ "And how much does the electricity cost? These prices are in fact **shadow prices** taken from the **dual variables** of the model solution.\n",
+ "They reflect the marginal cost of electricity generation (i.e., the additional cost of the system for supplying one more unit of\n",
+ "electricity), which is in fact the marginal cost of the most expensive operating generator. \n",
+ "\n",
+ "Note the price drop when the most expensive technology is no longer in the system."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# Replace the technology filters with a commodity filter;\n",
+ "# show only \"light\" and not e.g. \"electricity\".\n",
+ "rep.set_filters(c=[\"light\"])\n",
+ "\n",
+ "# Create a price plot\n",
+ "rep.get(\"plot prices\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Close the connection to the database\n",
+ "\n",
+ "When working with local HSQLDB database instances, you cannot connect to one database from multipe Jupyter notebooks (or processes) at the same time.\n",
+ "\n",
+ "If you want to easily switch between notebooks with connections to the same `ixmp` database, you need to close the connection in one notebook before initializing the platform using `ixmp.Platform()` in another notebook.\n",
+ "\n",
+ "After having closed the database connection, you can reopen it using\n",
+ "```\n",
+ "mp.open_db()\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "skip"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "mp.close_db()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "## Congratulations! \n",
+ "\n",
+ "You have built and run your very first *MESSAGEix* model. Welcome to the community!\n",
+ "\n",
+ "The next tutorials will introduce you to other features of the framework, including energy system constraints, emissions taxes, and other policy options.\n",
+ "\n",
+ "Check us out on Github https://github.com/iiasa/message_ix \n",
+ "and get in touch with us online https://groups.google.com/forum/message-ix ..."
+ ]
+ }
+ ],
+ "metadata": {
+ "anaconda-cloud": {},
+ "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.8.5"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}