Skip to content

Commit 7b733f6

Browse files
committed
TEMPORARY Add notebook to troubleshoot test_price_duality
1 parent 28ad9b4 commit 7b733f6

File tree

1 file changed

+327
-0
lines changed

1 file changed

+327
-0
lines changed

Diff for: message_ix/tests/feature_price_emission.ipynb

+327
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,327 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": null,
6+
"metadata": {},
7+
"outputs": [],
8+
"source": [
9+
"from ixmp import Platform\n",
10+
"\n",
11+
"from message_ix import Scenario\n",
12+
"\n",
13+
"MODEL = \"test_emissions_price\"\n",
14+
"\n",
15+
"mp = Platform(\"test_feature_price_emission\")\n",
16+
"mp.add_unit(\"MtCO2\")\n",
17+
"mp.add_unit(\"tCO2/kWa\")\n",
18+
"mp.add_unit(\"USD/kW\")\n",
19+
"\n",
20+
"scen = Scenario(\n",
21+
" mp,\n",
22+
" MODEL,\n",
23+
" scenario=\"many_tecs\",\n",
24+
" version=\"new\",\n",
25+
")"
26+
]
27+
},
28+
{
29+
"cell_type": "code",
30+
"execution_count": null,
31+
"metadata": {},
32+
"outputs": [],
33+
"source": [
34+
"from message_ix.tests.test_feature_price_emission import model_setup\n",
35+
"\n",
36+
"# 450 is too much; this bound will not affect the first model year\n",
37+
"# (EMISS is not reduced from without cumulative bound to with it)\n",
38+
"# In a model year without binding bound, no price_emission is produced ->\n",
39+
"# there is one value missing for price_emission in period-specific bound\n",
40+
"cumulative_bound = 1\n",
41+
"# cumulative_bound = 500\n",
42+
"# cumulative_bound = 550\n",
43+
"years = [2020, 2030, 2040, 2050]\n",
44+
"# years = [2020, 2025, 2030, 2040, 2050]\n",
45+
"# years = [2020, 2030, 2040, 2045, 2050]\n",
46+
"\n",
47+
"filters = {\"node\": \"World\"}\n",
48+
"\n",
49+
"model_setup(scen=scen, years=years, simple_tecs=False)"
50+
]
51+
},
52+
{
53+
"cell_type": "code",
54+
"execution_count": null,
55+
"metadata": {},
56+
"outputs": [],
57+
"source": [
58+
"from message_ix.tests.test_feature_price_emission import solve_args\n",
59+
"\n",
60+
"scen.commit(\"initialize test scenario\")\n",
61+
"scen.solve(quiet=True, **solve_args)\n",
62+
"scen.var(\"EMISS\", filters)"
63+
]
64+
},
65+
{
66+
"cell_type": "code",
67+
"execution_count": null,
68+
"metadata": {},
69+
"outputs": [],
70+
"source": [
71+
"scenario_cumulative_bound = scen.clone(\n",
72+
" MODEL,\n",
73+
" \"cumulative_emission_bound\",\n",
74+
" \"introducing a cumulative emissions bound\",\n",
75+
" keep_solution=False,\n",
76+
")\n",
77+
"scenario_cumulative_bound.check_out()\n",
78+
"\n",
79+
"scenario_cumulative_bound.add_cat(\"year\", \"cumulative\", years)\n",
80+
"scenario_cumulative_bound.add_par(\n",
81+
" \"bound_emission\",\n",
82+
" [\"World\", \"GHG\", \"all\", \"cumulative\"],\n",
83+
" cumulative_bound,\n",
84+
" \"MtCO2\",\n",
85+
")\n",
86+
"scenario_cumulative_bound.commit(\"initialize test scenario\")\n",
87+
"scenario_cumulative_bound.solve(quiet=True, **solve_args)\n",
88+
"scenario_cumulative_bound.var(\"EMISS\", filters)"
89+
]
90+
},
91+
{
92+
"cell_type": "code",
93+
"execution_count": null,
94+
"metadata": {},
95+
"outputs": [],
96+
"source": [
97+
"emiss = scenario_cumulative_bound.var(\"EMISS\", filters).set_index(\"year\").lvl\n",
98+
"price_emission = (\n",
99+
" scenario_cumulative_bound.var(\"PRICE_EMISSION\", filters).set_index(\"year\").lvl\n",
100+
")"
101+
]
102+
},
103+
{
104+
"cell_type": "code",
105+
"execution_count": null,
106+
"metadata": {},
107+
"outputs": [],
108+
"source": [
109+
"# --------------------------------------------------------\n",
110+
"# Run scenario with annual-emission bound based on `EMISS`\n",
111+
"# from cumulative constraint scenario.\n",
112+
"# --------------------------------------------------------\n",
113+
"\n",
114+
"scenario_period_bound = scen.clone(\n",
115+
" MODEL,\n",
116+
" \"period_bound_many_tecs\",\n",
117+
" \"introducing a period-specific emission_bound\",\n",
118+
" keep_solution=False,\n",
119+
")\n",
120+
"scenario_period_bound.check_out()\n",
121+
"for year in years:\n",
122+
" scenario_period_bound.add_cat(\"year\", year, year)\n",
123+
"\n",
124+
"# use emissions from cumulative-constraint scenario as period-emission bounds\n",
125+
"emiss_period_bound = (\n",
126+
" scenario_cumulative_bound.var(\"EMISS\", {\"node\": \"World\"})\n",
127+
" .rename(columns={\"year\": \"type_year\", \"lvl\": \"value\"})\n",
128+
" .drop(\"emission\", axis=1)\n",
129+
")\n",
130+
"emiss_period_bound[\"type_emission\"] = \"GHG\"\n",
131+
"emiss_period_bound[\"unit\"] = \"MtCO2\"\n",
132+
"scenario_period_bound.add_par(\"bound_emission\", emiss_period_bound)\n",
133+
"scenario_period_bound.commit(\"initialize test scenario for periodic emission bound\")\n",
134+
"scenario_period_bound.solve(quiet=True, **solve_args)\n",
135+
"scenario_period_bound.var(\"EMISS\", filters)"
136+
]
137+
},
138+
{
139+
"cell_type": "code",
140+
"execution_count": null,
141+
"metadata": {},
142+
"outputs": [],
143+
"source": [
144+
"import numpy.testing as npt\n",
145+
"\n",
146+
"# check -emissions are close between cumulative and yearly-bound scenarios\n",
147+
"emiss_period_bound = scenario_period_bound.var(\"EMISS\", filters).set_index(\"year\").lvl\n",
148+
"npt.assert_allclose(emiss, emiss_period_bound)"
149+
]
150+
},
151+
{
152+
"cell_type": "code",
153+
"execution_count": null,
154+
"metadata": {},
155+
"outputs": [],
156+
"source": [
157+
"scenario_cumulative_bound.par(\"emission_factor\")"
158+
]
159+
},
160+
{
161+
"cell_type": "code",
162+
"execution_count": null,
163+
"metadata": {},
164+
"outputs": [],
165+
"source": [
166+
"print(price_emission)\n",
167+
"scenario_period_bound.var(\"PRICE_EMISSION\")"
168+
]
169+
},
170+
{
171+
"cell_type": "code",
172+
"execution_count": null,
173+
"metadata": {},
174+
"outputs": [],
175+
"source": [
176+
"# check \"PRICE_EMISSION\" is close between cumulative- and yearly-bound scenarios\n",
177+
"price_emission_period_bound = (\n",
178+
" scenario_period_bound.var(\"PRICE_EMISSION\", filters).set_index(\"year\").lvl\n",
179+
")\n",
180+
"npt.assert_allclose(price_emission, price_emission_period_bound)"
181+
]
182+
},
183+
{
184+
"cell_type": "code",
185+
"execution_count": null,
186+
"metadata": {},
187+
"outputs": [],
188+
"source": [
189+
"scenario_cumulative_bound.par(\"bound_emission\")"
190+
]
191+
},
192+
{
193+
"cell_type": "code",
194+
"execution_count": null,
195+
"metadata": {},
196+
"outputs": [],
197+
"source": [
198+
"scen_tax = Scenario(\n",
199+
" mp,\n",
200+
" MODEL,\n",
201+
" scenario=\"tax_many_tecs\",\n",
202+
" version=\"new\",\n",
203+
")\n",
204+
"model_setup(scen_tax, years, simple_tecs=False)\n",
205+
"for year in years:\n",
206+
" scen_tax.add_cat(\"year\", year, year)\n",
207+
"# use emission prices from cumulative-constraint scenario as taxes\n",
208+
"taxes = scenario_cumulative_bound.var(\"PRICE_EMISSION\").rename(\n",
209+
" columns={\"year\": \"type_year\", \"lvl\": \"value\"}\n",
210+
")\n",
211+
"taxes[\"unit\"] = \"USD/tCO2\"\n",
212+
"taxes[\"node\"] = \"node\"\n",
213+
"scen_tax.add_par(\"tax_emission\", taxes)"
214+
]
215+
},
216+
{
217+
"cell_type": "code",
218+
"execution_count": null,
219+
"metadata": {},
220+
"outputs": [],
221+
"source": [
222+
"scen_tax.commit(\"initialize test scenario for taxes\")\n",
223+
"scen_tax.solve(quiet=True)"
224+
]
225+
},
226+
{
227+
"cell_type": "code",
228+
"execution_count": null,
229+
"metadata": {},
230+
"outputs": [],
231+
"source": [
232+
"print(scenario_cumulative_bound.var(\"PRICE_EMISSION\"))\n",
233+
"print(scen_tax.var(\"PRICE_EMISSION\"))\n",
234+
"print(scen_tax.par(\"tax_emission\"))\n",
235+
"print(scenario_cumulative_bound.var(\"EMISS\"))\n",
236+
"print(scen_tax.var(\"EMISS\"))"
237+
]
238+
},
239+
{
240+
"cell_type": "code",
241+
"execution_count": null,
242+
"metadata": {},
243+
"outputs": [],
244+
"source": [
245+
"print(scenario_cumulative_bound.var(\"ACT\"))"
246+
]
247+
},
248+
{
249+
"cell_type": "code",
250+
"execution_count": null,
251+
"metadata": {},
252+
"outputs": [],
253+
"source": [
254+
"print(scen_tax.var(\"ACT\"))"
255+
]
256+
},
257+
{
258+
"cell_type": "code",
259+
"execution_count": null,
260+
"metadata": {},
261+
"outputs": [],
262+
"source": [
263+
"scenario_cumulative_bound.par(\"demand\")"
264+
]
265+
},
266+
{
267+
"cell_type": "code",
268+
"execution_count": null,
269+
"metadata": {},
270+
"outputs": [],
271+
"source": [
272+
"scenario_cumulative_bound.equ(\"EMISSION_EQUIVALENCE\")"
273+
]
274+
},
275+
{
276+
"cell_type": "code",
277+
"execution_count": null,
278+
"metadata": {},
279+
"outputs": [],
280+
"source": [
281+
"price_emission_tax = scen_tax.var(\"PRICE_EMISSION\").set_index(\"year\").lvl\n",
282+
"npt.assert_allclose(price_emission, price_emission_tax)"
283+
]
284+
},
285+
{
286+
"cell_type": "code",
287+
"execution_count": null,
288+
"metadata": {},
289+
"outputs": [],
290+
"source": [
291+
"# check emissions are close between cumulative and tax scenarios\n",
292+
"emiss_tax = scen_tax.var(\"EMISS\", filters).set_index(\"year\").lvl\n",
293+
"npt.assert_allclose(emiss, emiss_tax, rtol=0.05)"
294+
]
295+
},
296+
{
297+
"cell_type": "code",
298+
"execution_count": null,
299+
"metadata": {},
300+
"outputs": [],
301+
"source": [
302+
"mp.close_db()"
303+
]
304+
}
305+
],
306+
"metadata": {
307+
"kernelspec": {
308+
"display_name": "mix312",
309+
"language": "python",
310+
"name": "python3"
311+
},
312+
"language_info": {
313+
"codemirror_mode": {
314+
"name": "ipython",
315+
"version": 3
316+
},
317+
"file_extension": ".py",
318+
"mimetype": "text/x-python",
319+
"name": "python",
320+
"nbconvert_exporter": "python",
321+
"pygments_lexer": "ipython3",
322+
"version": "3.12.3"
323+
}
324+
},
325+
"nbformat": 4,
326+
"nbformat_minor": 2
327+
}

0 commit comments

Comments
 (0)