Update toy_model.py

Increased heat capacity of all components, resulting in more realistic physics (i.e. no immediate blowup). Also implemented toggle for velocity calculations (now largely redundant). Various other fiddles.
This commit is contained in:
Simon Clark 2020-06-17 17:17:11 +01:00
parent df23337825
commit d6f83e4558
1 changed files with 38 additions and 29 deletions

View File

@ -9,7 +9,7 @@ import time, sys
# define temporal parameters, including the length of time between calculation of fields and the length of a day on the planet (used for calculating Coriolis as well) # define temporal parameters, including the length of time between calculation of fields and the length of a day on the planet (used for calculating Coriolis as well)
day = 60*60*24 day = 60*60*24
dt = 60*6 ###### <----- TIMESTEP dt = 60*17 ###### <----- TIMESTEP
# power incident on (lat,lon) at time t # power incident on (lat,lon) at time t
def solar(insolation, lat, lon, t): def solar(insolation, lat, lon, t):
@ -35,25 +35,26 @@ lon_plot, lat_plot = np.meshgrid(lon, lat)
temperature_planet = np.zeros((nlat,nlon)) + 270 temperature_planet = np.zeros((nlat,nlon)) + 270
temperature_atmosp = np.zeros((nlat,nlon)) + 270 temperature_atmosp = np.zeros((nlat,nlon)) + 270
albedo = np.zeros((nlat,nlon)) + 0.5 albedo = np.zeros((nlat,nlon)) + 0.5
heat_capacity_earth = np.zeros((nlat,nlon)) + 1E5 heat_capacity_earth = np.zeros((nlat,nlon)) + 1E6
air_pressure = np.zeros((nlat,nlon)) air_pressure = np.zeros((nlat,nlon))
u = np.zeros((nlat,nlon)) u = np.zeros((nlat,nlon))
v = np.zeros((nlat,nlon)) v = np.zeros((nlat,nlon))
air_density = np.zeros_like(air_pressure) + 1.3 air_density = np.zeros_like(air_pressure) + 1.3
# custom oceans with lower albedo and higher heat capacity # custom oceans with lower albedo and higher heat capacity
ocean = False ocean = True
if ocean: if ocean:
albedo[5:55,9:20] = 0.2 albedo[5:55,9:20] = 0.7
albedo[23:50,45:70] = 0.2 albedo[23:50,45:70] = 0.7
albedo[2:30,85:110] = 0.2 albedo[2:30,85:110] = 0.7
heat_capacity_earth[5:55,9:20] = 1E6 heat_capacity_earth[5:55,9:20] *= 2
heat_capacity_earth[23:50,45:70] = 1E6 heat_capacity_earth[23:50,45:70] *= 2
heat_capacity_earth[2:30,85:110] = 1E6 heat_capacity_earth[2:30,85:110] *= 2
# define physical constants # define physical constants
epsilon = 0.75 epsilon = 0.75
heat_capacity_atmos = 1E3 epsilon = 0.75
heat_capacity_atmos = 1E7
specific_gas = 287 specific_gas = 287
thermal_diffusivity_air = 20E-6 thermal_diffusivity_air = 20E-6
thermal_diffusivity_roc = 1.5E-6 thermal_diffusivity_roc = 1.5E-6
@ -114,23 +115,29 @@ ax[1].set_title('Atmosphere temperature')
plt.ion() plt.ion()
plt.show() plt.show()
# if you want to include advection set this to be True advection = True # can turn thermal and mass advection on or off
advection = True boundary = 5 # advection will occur starting from this many gridpoints away from the poles
while True: while True:
# print current time in simulation to command line # print current time in simulation to command line
print("t = " + str(round(t/day,2)) + " days", end='\r') print("t = " + str(round(t/day,2)) + " days", end='\r')
# print(u.max(),air_density.max(),air_density.min()) print(u.max(),u.min(),v.max(),v.min(),air_density.max(),air_density.min())
if t < day*2:
dt = 60*71
velocity = False
else:
dt = 60*7
velocity = True
# calculate change in temperature of ground and atmosphere due to radiative imbalance # calculate change in temperature of ground and atmosphere due to radiative imbalance
for i in range(nlat): for i in range(nlat):
for j in range(nlon): for j in range(nlon):
temperature_planet[i,j] += dt*(albedo[i,j]*solar(insolation,lat[i],lon[j],t) + epsilon*sigma*temperature_atmosp[i,j]**4 - sigma*temperature_planet[i,j]**4)/heat_capacity_earth[i,j] temperature_planet[i,j] += dt*(albedo[i,j]*solar(insolation,lat[i],lon[j],t) + epsilon*sigma*temperature_atmosp[i,j]**4 - sigma*temperature_planet[i,j]**4)/heat_capacity_earth[i,j]
temperature_atmosp[i,j] += dt*(epsilon*sigma*temperature_planet[i,j]**4 - 2*epsilon*sigma*temperature_atmosp[i,j]**4)/heat_capacity_atmos temperature_atmosp[i,j] += dt*(epsilon*sigma*temperature_planet[i,j]**4 - 2*epsilon*sigma*temperature_atmosp[i,j]**4)/(heat_capacity_atmos*air_density[i,j])
if advection: if advection:
boundary = 10
# allow for thermal advection in the atmosphere, and heat diffusion in the atmosphere and the ground # allow for thermal advection in the atmosphere, and heat diffusion in the atmosphere and the ground
atmosp_addition = dt*divergence_with_scalar(temperature_atmosp) atmosp_addition = dt*divergence_with_scalar(temperature_atmosp)
temperature_atmosp[boundary:-boundary,:] -= atmosp_addition[boundary:-boundary,:] temperature_atmosp[boundary:-boundary,:] -= atmosp_addition[boundary:-boundary,:]
@ -141,26 +148,28 @@ while True:
temperature_atmosp += dt*(thermal_diffusivity_air*laplacian(temperature_atmosp)) temperature_atmosp += dt*(thermal_diffusivity_air*laplacian(temperature_atmosp))
temperature_planet += dt*(thermal_diffusivity_roc*laplacian(temperature_planet)) temperature_planet += dt*(thermal_diffusivity_roc*laplacian(temperature_planet))
# update air pressure # update air pressure
air_pressure = air_density*specific_gas*temperature_atmosp air_pressure = air_density*specific_gas*temperature_atmosp
if velocity:
u_temp = np.zeros_like(u)
v_temp = np.zeros_like(v)
u_temp = np.zeros_like(u) # calculate acceleration of atmosphere using primitive equations on beta-plane
v_temp = np.zeros_like(v) for i in np.arange(boundary,nlat-boundary):
for j in range(nlon):
u_temp[i,j] = dt*( - scalar_gradient_x(air_pressure,i,j)/air_density[i,j] + coriolis[i]*v[i,j] - u[i,j]*scalar_gradient_x(u,i,j) - v[i,j]*scalar_gradient_y(u,i,j))
v_temp[i,j] = dt*( - scalar_gradient_y(air_pressure,i,j)/air_density[i,j] - coriolis[i]*u[i,j] - u[i,j]*scalar_gradient_x(v,i,j) - v[i,j]*scalar_gradient_y(v,i,j))
# calculate acceleration of atmosphere using primitive equations on beta-plane u += u_temp
for i in np.arange(1,nlat-1): v += v_temp
for j in range(nlon):
u_temp[i,j] += dt*( - scalar_gradient_x(air_pressure,i,j)/air_density[i,j] + coriolis[i]*v[i,j] - u[i,j]*scalar_gradient_x(u,i,j) - v[i,j]*scalar_gradient_y(u,i,j))
v_temp[i,j] += dt*( - scalar_gradient_y(air_pressure,i,j)/air_density[i,j] - coriolis[i]*u[i,j] - u[i,j]*scalar_gradient_x(v,i,j) - v[i,j]*scalar_gradient_y(v,i,j))
u += u_temp
v += v_temp
# update plot # update plot
test = ax[0].contourf(lon_plot, lat_plot, temperature_planet, cmap='seismic') ax[0].contourf(lon_plot, lat_plot, temperature_planet, cmap='seismic')
ax[1].contourf(lon_plot, lat_plot, temperature_atmosp, cmap='seismic') test = ax[1].contourf(lon_plot, lat_plot, temperature_atmosp, cmap='seismic')
ax[1].quiver(lon_plot[::3, ::3],lat_plot[::3, ::3],u[::3, ::3],v[::3, ::3]) # ax[1].quiver(lon_plot[::3, ::3],lat_plot[::3, ::3],u[::3, ::3],v[::3, ::3])
ax[1].streamplot(lon_plot,lat_plot,u,v,density=0.75,color='black')
ax[0].set_title('$\it{Ground} \quad \it{temperature}$') ax[0].set_title('$\it{Ground} \quad \it{temperature}$')
ax[1].set_title('$\it{Atmospheric} \quad \it{temperature}$') ax[1].set_title('$\it{Atmospheric} \quad \it{temperature}$')
for i in ax: for i in ax: