├── .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 | --------------------------------------------------------------------------------