Script for solving the 1D diffusion equation

We will solve for the cooling of hot dike that was emplaced into cooler country rock. The method we are using is a simple explicit 1D finite differences scheme.

First we load some useful libraries

[1]:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
from IPython.display import HTML
from matplotlib.patches import Rectangle

Next we define some physics constants

[2]:
L       = 100           # Length of modeled domain [m]
Tmagma  = 1200          # Temperature of magma [C]
Trock   = 300           # Temperature of country rock [C]
kappa   = 1e-6          # Thermal diffusivity of rock [m2/s]
W       = 5;            # Width of dike [m]
day     = 60*60*24       # # seconds per day
dt      = 1*day         # Timestep [s]

and some numerical constants constants

[3]:
nx      = 201                                          # Number of gridpoints in x-direction
nt      = 500                                          # Number of timesteps to compute
Xvec,dx = np.linspace(-L/2, L/2, nx,  retstep=True)    # X coordinate vector, constant spacing
beta    = kappa*dt/dx**2

Set the initial conditions

[4]:
T_init  = np.ones(nx)*Trock;              # everything is cold initially
T_init[np.nonzero(np.abs(Xvec) <= W/2)] = Tmagma   # and hot where the dike is
time    = 0

Make a function that computes temperature

[5]:
# hide
# only store the latest time step solution to Told
def fdm_solve(Told):
    Tnew=Told.copy()
    for i in range(1,len(Xvec)-1):
        Tnew[i] = beta * (Told[i+1] - 2*Told[i] + Told[i-1]) + Told[i]
    return Tnew
[6]:
# write a function that solves for temperature!

#def fdm_solve(Told):
#    Tnew=Told.copy()
#    for i in range(1,len(Xvec)-1):
#        Tnew[i] = ???
#    return Tnew

Compute and visualize everything

[7]:
# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure(figsize=(10,5))
ax = plt.axes(xlim=(-L/2, L/2), ylim=(0, Tmagma))
ax.add_patch(Rectangle((-W/2, 0), W, 1200, alpha=0.5, color='tab:red'))
line, = ax.plot([], [], lw=1)
timeLabel=ax.text(0.02,0.98,'Time: ',transform=ax.transAxes,va='top')
ax.set_xlabel('X (m)')
ax.set_ylabel('Temperature ($^{\circ}$C)')

# Initialization function: plot the background of each frame
def init():
    line.set_data([], [])
    return line,

# Initialize Tnew
Tnew=T_init
# Animation function which updates figure data.  This is called sequentially
def animate(i):
    timeLabel._text='Time: %.1f day'%(i*dt/day)

    # use global keyword to store the latest solution and update it using fdm_solve function
    global Tnew
    Tnew=fdm_solve(Tnew)
    line.set_data(Xvec, Tnew)

    return line,

# Call the animator.  blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, init_func=init,
                               frames=nt, interval=30, blit=True)

plt.close(anim._fig)

# Call function to display the animation
#HTML(anim.to_html5_video())  # lower resolution
HTML(anim.to_jshtml())  # higher resolution
[7]:
[ ]: