├── .ipynb_checkpoints
├── DICE_Demonstration-checkpoint.ipynb
└── Untitled-checkpoint.ipynb
├── DICE_Demonstration.ipynb
├── README.md
├── __pycache__
├── economy_model.cpython-36.pyc
├── economy_model.cpython-37.pyc
├── util.cpython-36.pyc
├── util.cpython-37.pyc
├── visualization.cpython-36.pyc
└── visualization.cpython-37.pyc
├── climate_model.py
├── economy_model.py
├── results
└── before_emissions.png
├── util.py
└── visualization.py
/.ipynb_checkpoints/Untitled-checkpoint.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [],
3 | "metadata": {},
4 | "nbformat": 4,
5 | "nbformat_minor": 2
6 | }
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Python-DICE
2 | Python 3.6 implementation of Dynamic Integrated Climate-Economy model (DICE), the model integrates in an end-to-end fashion the economics, carbon cycle, climate science, and impacts in a highly aggregated model that allows a weighing of the costs and benefits of taking steps to slow greenhouse warming. We support the interactive visulisation of the evolved parameters of the model with Plotly.js backend.
3 |
4 | This work is done as a part of the Climate Change AI Project at MILA by Shivam Patel under the guidance of Dr S. Karthik Mukkavilli and Prof. Yoshua Bengio .
5 |
--------------------------------------------------------------------------------
/__pycache__/economy_model.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Shivamshaiv/Python-DICE/c31a54f79e9c910b7575688a7b133d19fa8d8676/__pycache__/economy_model.cpython-36.pyc
--------------------------------------------------------------------------------
/__pycache__/economy_model.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Shivamshaiv/Python-DICE/c31a54f79e9c910b7575688a7b133d19fa8d8676/__pycache__/economy_model.cpython-37.pyc
--------------------------------------------------------------------------------
/__pycache__/util.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Shivamshaiv/Python-DICE/c31a54f79e9c910b7575688a7b133d19fa8d8676/__pycache__/util.cpython-36.pyc
--------------------------------------------------------------------------------
/__pycache__/util.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Shivamshaiv/Python-DICE/c31a54f79e9c910b7575688a7b133d19fa8d8676/__pycache__/util.cpython-37.pyc
--------------------------------------------------------------------------------
/__pycache__/visualization.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Shivamshaiv/Python-DICE/c31a54f79e9c910b7575688a7b133d19fa8d8676/__pycache__/visualization.cpython-36.pyc
--------------------------------------------------------------------------------
/__pycache__/visualization.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Shivamshaiv/Python-DICE/c31a54f79e9c910b7575688a7b133d19fa8d8676/__pycache__/visualization.cpython-37.pyc
--------------------------------------------------------------------------------
/climate_model.py:
--------------------------------------------------------------------------------
1 | from economy_model import Economy
2 | import math
3 | import numpy as np
4 |
5 |
6 | class Climate:
7 | def __init__(self, econ):
8 | self.E_ind = [econ.sigma[0]]
9 | self.E = [self.E_ind[0] + self.E_land[0]]
10 |
--------------------------------------------------------------------------------
/economy_model.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from util import compute_external_forcing
3 | from util import update_carbon_masses
4 | from util import productivity
5 | from util import abatement_phi
6 | from util import emmision_control_from_carbontax
7 | import math
8 | import matplotlib.pyplot as plt
9 |
10 |
11 | class Economy:
12 | def __init__(
13 | self,
14 | start_year=2005,
15 | social_time_prefrence_rate_rho=0.015,
16 | elasticity_marginal_utility_alpha=1.5,
17 | coef_on_damage_exponent_pi2=0.0028,
18 | damage_exponent_epsilon=2,
19 | exponent_emission_reduction_theta2=2.8,
20 | production_gamma=0.300,
21 | saving_rate_s=0.22,
22 | preindustrail_carbon_Mpi=592,
23 | ):
24 | productivity = (
25 | lambda A, K, L, gamma: A * np.power(K, gamma) * np.power(L, 1 - gamma)
26 | ) # Productivity Function
27 | abatement_phi = lambda time: 1 # Temp abatement.
28 | self.start_year = start_year # The starting year of the simulation where all values are caliberated.
29 | self.time = 0
30 | self.L = [6411] # World Population in millions
31 | self.L_g = [0.5]
32 | self.R = [
33 | 1 / (1 + social_time_prefrence_rate_rho)
34 | ] # Social Time Discount factor
35 | self.A = [0.0303220]
36 | self.A_g = [0.16] # Initial growth rate of TFP per decade
37 | self.K = [137] # 2005 capital value
38 | self.sigma_g = [
39 | 0.158
40 | ] # Initial rate of decline of carbon intensity per period
41 | self.sigma = [0.14452] # 2005 Effective Carbon Intensity
42 | self.T_at = [0.83] # Temperature change from 1900 until 2000
43 | self.omega = [
44 | 1
45 | - (
46 | 1
47 | / (
48 | 1
49 | + (
50 | coef_on_damage_exponent_pi2
51 | * np.power(self.T_at[0], damage_exponent_epsilon)
52 | )
53 | )
54 | )
55 | ]
56 | self.tipping_omega = [
57 | 1
58 | - np.power(
59 | (
60 | 1
61 | + np.power(self.T_at[-1] / 20.46, 2)
62 | + np.power(self.T_at[-1] / 6.081, 6.754)
63 | ),
64 | -1,
65 | )
66 | ]
67 | self.BC = [1.26] # Cost of backstop technology
68 | self.mu = [1]
69 | self.Eind = [
70 | (self.sigma[0])
71 | * (1 - self.mu[0])
72 | * productivity(self.A[0], self.K[0], self.L[0], production_gamma)
73 | ]
74 | self.lmbda = [
75 | (
76 | np.power(
77 | abatement_phi(self.time), 1 - exponent_emission_reduction_theta2
78 | )
79 | * self.BC[0]
80 | * np.power(self.mu[0], exponent_emission_reduction_theta2)
81 | * self.sigma[0]
82 | )
83 | / exponent_emission_reduction_theta2
84 | ]
85 | self.Y = [productivity(self.A[0], self.K[0], self.L[0], production_gamma)]
86 | # self.Q = [((1 - self.omega)*(1 - self.lmbda))*self.Y]
87 | self.Q = [55.34]
88 | self.I = [saving_rate_s * self.Q[0]]
89 | self.C = [
90 | self.Q[0] - self.I[0]
91 | ] # Total consumption, trillions of 2005 US dollars
92 | self.c = [
93 | self.C[0] / self.L[0]
94 | ] # per capita consumption, thosands of 2005 US dollars
95 | self.U = [
96 | (np.power(self.c[0], 1 - elasticity_marginal_utility_alpha))
97 | / (1 - elasticity_marginal_utility_alpha)
98 | + 1
99 | ]
100 | self.test = []
101 |
102 | self.E_ind = [self.sigma[0] * self.Y[0]]
103 | # self.E_ind = [84.1910-1.1]
104 | self.E_land = [
105 | 1.1
106 | ] # Carbon emissions from land use (ie, deforestation), GtC per period
107 | self.E = [self.E_ind[-1] + self.E_land[-1]]
108 | self.E_cum = [self.E[-1]]
109 | self.Tax_tau = self.BC[0] * pow(
110 | self.mu[0], exponent_emission_reduction_theta2 - 1
111 | ) # Carbon Tax
112 |
113 | self.M_at = [787] # Mass of carbon in the atmosphere in 2005
114 | self.M_up = [1600] # Mass of carbon in the upper ocean in 2005
115 | self.M_lo = [10100] # Mass of carbon in the lower ocean in 2005
116 |
117 | self.T_lo = [
118 | 0.0068
119 | ] # Temperature change in the lower ocean from 1900 until 2000
120 | self.F_ex = [0.83]
121 | self.F_ex0 = self.F_ex[0] # Non-CO2 forcings in 2005
122 | self.F_ex10 = 0.30 # Estimate of non-CO2 forcings in 2100
123 |
124 | self.W = [self.L[-1] * self.U[-1] * self.R[-1]]
125 |
126 | ##### Connstants ############
127 | self.social_time_prefrence_rate_rho = social_time_prefrence_rate_rho
128 | self.elasticity_marginal_utility_alpha = elasticity_marginal_utility_alpha
129 | self.coef_on_damage_exponent_pi2 = coef_on_damage_exponent_pi2
130 | self.damage_exponent_epsilon = damage_exponent_epsilon
131 | self.exponent_emission_reduction_theta2 = exponent_emission_reduction_theta2
132 | self.production_gamma = production_gamma
133 | self.saving_rate_s = saving_rate_s
134 | self.preindustrail_carbon_Mpi = preindustrail_carbon_Mpi
135 | self.L_Tmax = 8700 # Asymptotic population in the last period
136 | self.tech_change_decline_deltaa = 0.9
137 | self.depreciation_technological_change_δK = 0.1
138 | self.decline_rate_decarbonisation_σd1 = 0.006
139 | self.temp_increase_doubling_co2 = (
140 | 3.2 # Temperature increase (◦C) from a doubling of preindustrial CO2.
141 | )
142 | self.costdecinline_backstop_tech_percent_BCg = 0.05
143 | self.fossil_remaining_Ccum = 6000
144 | self.pop_growth_pop_perdecade_Lg = 0.5
145 | self.declinerate_growth_productivity_deltab = 0.2
146 |
147 | # Climate Connstants
148 | self.F2CO2 = 3.8 # Forcing from a doubling of preindustrial CO2
149 | self.ξ1 = (
150 | 0.220 # Inverse of thermal capacity of the atmosphere and the upper ocean.
151 | )
152 | self.ξ2 = 0.310 # Ratio of the thermal capacity of the deep oceans to the transfer rate from the shallow ocean to the deep ocean
153 | self.ξ3 = (
154 | 0.050 # Transfer rate of heat from the upper ocean to the deep ocean.
155 | )
156 |
157 | self.F = [
158 | self.F2CO2 * (np.log2(self.M_at[0] / self.preindustrail_carbon_Mpi))
159 | + self.F_ex0
160 | ] # Forcing due to CO2
161 |
162 | def loop(self, t, tipping_damage=False, temp_model="linear", carbon_tax=(0, 0, 0)):
163 | for time in range(t):
164 | self.time = time
165 | self.L_g.append(
166 | (np.exp(self.L_g[0] * (time + 1)) - 1)
167 | / (np.exp(self.L_g[0] * (time + 1)) - 0)
168 | )
169 | self.L.append(
170 | self.L[-1] * (np.power(self.L_Tmax / self.L[-1], self.L_g[-1]))
171 | )
172 | self.R.append(
173 | 1 / np.power(1 + self.social_time_prefrence_rate_rho, self.time)
174 | )
175 | self.T_lo.append(
176 | self.T_lo[-1] + (self.ξ3 * (self.T_at[-1] - self.T_lo[-1]))
177 | )
178 | const_lamb = self.F2CO2 / self.temp_increase_doubling_co2
179 | self.F_ex.append(compute_external_forcing(self, time))
180 |
181 | # Update A(t)
182 | self.A_g.append(
183 | self.A_g[0]
184 | * np.exp(
185 | -self.tech_change_decline_deltaa
186 | * 1
187 | * time
188 | * np.exp(-self.declinerate_growth_productivity_deltab * time)
189 | )
190 | )
191 | self.A.append((self.A[-1]) / (1 - self.A_g[-2]))
192 |
193 | # Update K(t)
194 | self.K.append(
195 | self.I[-1]
196 | + (
197 | np.power((1 - self.depreciation_technological_change_δK), 1)
198 | * (self.K[-1] * 1)
199 | )
200 | )
201 |
202 | # Update productivity
203 | self.Y.append(
204 | productivity(self.A[-1], self.K[-1], self.L[-1], self.production_gamma)
205 | )
206 |
207 | self.sigma_g.append(
208 | self.sigma_g[-1] * (1 - self.decline_rate_decarbonisation_σd1) ** 1
209 | )
210 | self.sigma.append(self.sigma[-1] * (1 - self.sigma_g[-2]))
211 |
212 | # Emisssions
213 | self.E_land.append(self.E_land[0] * np.power(0.8, time))
214 | self.E_ind.append(self.sigma[-1] * (1 - self.mu[-1]) * self.Y[-1])
215 | self.E.append(self.E_land[-1] + self.E_ind[-1])
216 | self.E_cum.append(np.sum(self.E))
217 |
218 | update_carbon_masses(self)
219 | F_eta = 3.2 # Forcing of CO2
220 | self.F.append(
221 | F_eta * (np.log(self.M_at[-1] / self.preindustrail_carbon_Mpi))
222 | + self.F_ex[-1]
223 | )
224 |
225 | if temp_model == "default":
226 | self.T_at.append(
227 | self.T_at[-1]
228 | + self.ξ1
229 | * (
230 | (1) * self.F[-1]
231 | - const_lamb * self.T_at[-1]
232 | - self.ξ2 * (self.T_at[-1] - self.T_lo[-2])
233 | )
234 | )
235 | elif temp_model == "linear":
236 | # denom = (2*2*self.preindustrail_carbon_Mpi) - (0.94796*self.M_at[0]) - (0.00075*self.M_up[0])
237 | denom = (
238 | (2 * 2 * self.preindustrail_carbon_Mpi)
239 | - (-0.2 * self.M_at[0])
240 | - (0.001 * self.M_up[0])
241 | )
242 | self.T_at.append(
243 | self.T_at[0]
244 | + (self.time)
245 | * (self.E_cum[-1])
246 | * (self.temp_increase_doubling_co2 / (denom))
247 | )
248 | self.omega.append(
249 | 1
250 | - (
251 | 1
252 | / (
253 | 1
254 | + (
255 | self.coef_on_damage_exponent_pi2
256 | * np.power(self.T_at[-1], self.damage_exponent_epsilon)
257 | )
258 | )
259 | )
260 | )
261 | self.tipping_omega.append(
262 | 1
263 | - np.power(
264 | (
265 | 1
266 | + np.power(self.T_at[-1] / 20.46, 2)
267 | + np.power(self.T_at[-1] / 6.081, 6.754)
268 | ),
269 | -1,
270 | )
271 | )
272 |
273 | ### Abetement Function #To do
274 | self.BC.append(
275 | self.BC[0]
276 | * np.power(1 - self.costdecinline_backstop_tech_percent_BCg, self.time)
277 | )
278 | self.mu.append(emmision_control_from_carbontax(self, carbon_tax))
279 | self.lmbda.append(
280 | (
281 | np.power(
282 | abatement_phi(self.time),
283 | 1 - self.exponent_emission_reduction_theta2,
284 | )
285 | * self.BC[-1]
286 | * np.power(self.mu[-1], self.exponent_emission_reduction_theta2)
287 | * self.sigma[-1]
288 | )
289 | / self.exponent_emission_reduction_theta2
290 | )
291 |
292 | # Update Q production Function
293 | if tipping_damage:
294 | self.Q.append(
295 | (1 - self.tipping_omega[-1]) * (1 - self.lmbda[-1]) * self.Y[-1]
296 | )
297 | else:
298 | self.Q.append((1 - self.omega[-1]) * (1 - self.lmbda[-1]) * self.Y[-1])
299 |
300 | # Update the Investment.
301 | self.I.append(self.saving_rate_s * self.Q[-1])
302 |
303 | # Update the capital
304 | self.C.append(self.Q[-1] - self.I[-1])
305 | self.c.append(self.C[-1] / self.L[-1])
306 |
307 | # Update the utility
308 | self.U.append(
309 | (
310 | np.power(self.c[-1], 1 - self.elasticity_marginal_utility_alpha)
311 | / (1 - self.elasticity_marginal_utility_alpha)
312 | )
313 | + 1
314 | )
315 |
316 | self.test.append(emmision_control_from_carbontax(self, carbon_tax))
317 |
318 |
319 | model = Economy()
320 | # print(model.K[-1])
321 | # print(model.__dict__)
322 | model.loop(100)
323 | # print(model.U)
324 | # print(model.__dict__)
325 | # plt.plot(model.A_g)
326 |
327 | # plt.show()
328 |
--------------------------------------------------------------------------------
/results/before_emissions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Shivamshaiv/Python-DICE/c31a54f79e9c910b7575688a7b133d19fa8d8676/results/before_emissions.png
--------------------------------------------------------------------------------
/util.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 |
4 | def abatement_phi(time, phi0=1, phi5=1, phi10=1, phi15=1, phimax=1):
5 | if time < 5:
6 | return phi5 + (phi0 - phi5) * np.exp(-0.25 * time)
7 | elif time >= 5 and time < 10:
8 | return phi10 + (phi5 - phi10) * np.exp(-0.25 * time)
9 | elif time >= 10 and time < 15:
10 | return phi15 + (phi10 - phi15) * np.exp(-0.25 * time)
11 | else:
12 | return phi15 + (phimax - phi15) * np.exp(-0.25 * time)
13 |
14 |
15 | def productivity(A, K, L, gamma):
16 | return A * np.power(K, gamma) * np.power(L * 1, 1 - gamma)
17 |
18 |
19 | def compute_external_forcing(self, time):
20 | if time > 10:
21 | # return self.F_ex0 + 0.1*(self.F_ex0-self.F_ex10)*time
22 | return self.F_ex10
23 | else:
24 | return self.F_ex0 + 0.1 * (self.F_ex0 - self.F_ex10) * time
25 | # return self.F_ex0
26 |
27 |
28 | def update_carbon_masses(self):
29 | _b11, _b12, _b13 = 0.810712, 0.189288, 0
30 | _b21, _b22, _b23 = 0.097213, 0.852787, 0.05
31 | _b31, _b32, _b33 = 0, 0.003119, 0.996881
32 | self.carbon_matrix = np.array(
33 | [_b11, _b12, _b13, _b21, _b22, _b23, _b31, _b32, _b33,]
34 | ).reshape(3, 3)
35 |
36 | self.mass_matrix = np.array([[self.M_at[-1]], [self.M_up[-1]], [self.M_lo[-1]]])
37 | self.emmision_matrix = np.array([[5 * self.E[-1]], [0], [0]])
38 |
39 | new_masses = np.matmul(self.carbon_matrix, self.mass_matrix) + self.emmision_matrix
40 |
41 | self.M_at.append(new_masses[0][0])
42 | self.M_up.append(new_masses[1][0])
43 | self.M_lo.append(new_masses[2][0])
44 |
45 |
46 | def emmision_control_from_carbontax(self, carbon_tax):
47 | t5, t10, t15 = carbon_tax
48 | if self.time <= 10 and self.time > 5:
49 | output = np.power(
50 | t5 / self.BC[-1], 1 / (self.exponent_emission_reduction_theta2 - 1)
51 | )
52 | elif self.time <= 15 and self.time > 10:
53 | output = np.power(
54 | t10 / self.BC[-1], 1 / (self.exponent_emission_reduction_theta2 - 1)
55 | )
56 | elif self.time > 15:
57 | output = np.power(
58 | t15 / self.BC[-1], 1 / (self.exponent_emission_reduction_theta2 - 1)
59 | )
60 | else:
61 | output = 1
62 |
63 | if output > 1:
64 | output = self.mu[-1] # To check that there are no negative emissions.
65 | return output
66 |
--------------------------------------------------------------------------------
/visualization.py:
--------------------------------------------------------------------------------
1 | from economy_model import Economy
2 | import plotly.graph_objects as go
3 | import datetime
4 |
5 |
6 | def make_datetime(arr, start_year=2005):
7 | x = []
8 | for i in range(len(arr)):
9 | x.append(datetime.datetime(year=start_year + (5 * i), month=1, day=1))
10 | return x
11 |
12 |
13 | def plot_attr(
14 | arr, title="Evolution of the factor in the model", desc="Model Parameter"
15 | ):
16 | model = Economy()
17 | fig = go.Figure(
18 | data=go.Scatter(x=make_datetime(arr, start_year=model.start_year), y=arr),
19 | layout=go.Layout(title=title,),
20 | )
21 |
22 | fig.update_xaxes(title_text="Time in Years")
23 | fig.update_yaxes(title_text=desc)
24 |
25 | fig.update_layout(template="none")
26 | # fig = go.Figure(data=[go.Scatter(x=make_datetime(model.T_at), y=model.T_at)])
27 | # Use datetime objects to set xaxis range
28 | fig.update_layout(
29 | xaxis_range=[datetime.datetime(2001, 1, 1), make_datetime(arr)[-1]]
30 | )
31 | fig.show()
32 |
33 |
34 | def plot_temp_change(decades=10, tipping_damage=False, carbon_tax=(0, 0, 0)):
35 | model = Economy()
36 | model.loop(t=decades, tipping_damage=tipping_damage, carbon_tax=carbon_tax)
37 | fig = go.Figure(
38 | data=go.Scatter(
39 | x=make_datetime(model.T_at, start_year=model.start_year), y=model.T_at
40 | ),
41 | layout=go.Layout(title="Average Temperature Rise",),
42 | )
43 |
44 | fig.update_xaxes(title_text="Time in Years")
45 | fig.update_yaxes(title_text="Rise in Average Temperature since 1900")
46 |
47 | fig.update_layout(template="none")
48 | # fig = go.Figure(data=[go.Scatter(x=make_datetime(model.T_at), y=model.T_at)])
49 | # Use datetime objects to set xaxis range
50 | fig.update_layout(
51 | xaxis_range=[datetime.datetime(2001, 1, 1), make_datetime(model.T_at)[-1]]
52 | )
53 | fig.show()
54 |
55 |
56 | def plot_multiple_attr(main_arr):
57 | """
58 | Input an array in the format of [(arr_1,name_1),(arr_2,name_2),(arr_3,name_3),...,(arr_n,name_n)]
59 | Please ensure the sizes of all the arrays are same
60 | """
61 | fig = go.Figure()
62 | for tup in main_arr:
63 | arr, name = tup
64 | this_attr = go.Scatter(x=make_datetime(arr), y=arr, name=str(name))
65 | fig.add_trace(this_attr)
66 | fig.update_xaxes(title_text="Time in Years")
67 | fig.update_layout(template="none")
68 | fig.show()
69 |
70 |
71 | def give_temperature(decades, tipping_damage=False, carbon_tax=(0, 0, 0)):
72 | model = Economy()
73 | model.loop(decades, tipping_damage=tipping_damage, carbon_tax=carbon_tax)
74 | return model.T_at
75 |
76 |
77 | def plot_impact_of_carbon_tax(
78 | decades, tipping_damage=False, tax_arr=[], show_default=True
79 | ):
80 | """
81 | To see the impact of diffrent climate policies and represent them in one plot.
82 | Input : decades,tipping_damage,tax_arr
83 | Here tax_arr is an array of tuples with three values each : the amount of tax per topn of CO2 in 2050,2100
84 | and 2150.
85 | """
86 | fig = go.Figure()
87 | if show_default:
88 | default_arr = give_temperature(decades, tipping_damage=tipping_damage)
89 | fig.add_trace(
90 | go.Scatter(
91 | x=make_datetime(default_arr), y=default_arr, name="No Carbon Tax"
92 | )
93 | )
94 |
95 | # In the loop for the carbon tax senarios
96 | for carbon_tax_tup in tax_arr:
97 | arr = give_temperature(
98 | decades, tipping_damage=tipping_damage, carbon_tax=carbon_tax_tup
99 | )
100 | fig.add_trace(go.Scatter(x=make_datetime(arr), y=arr, name=str(carbon_tax_tup)))
101 |
102 | fig.update_xaxes(title_text="Time in Years")
103 | fig.update_layout(template="none")
104 | fig.show()
105 |
--------------------------------------------------------------------------------