Skip to content

Commit d34d1aa

Browse files
committed
Include the Python code needed in exercise
1 parent 3d45edd commit d34d1aa

File tree

2 files changed

+109
-0
lines changed

2 files changed

+109
-0
lines changed

interface/c/heat.py

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import numpy as np
2+
import matplotlib
3+
matplotlib.use('Agg')
4+
import matplotlib.pyplot as plt
5+
6+
# Set the colormap
7+
plt.rcParams['image.cmap'] = 'BrBG'
8+
9+
def evolve(u, u_previous, a, dt, dx2, dy2):
10+
"""Explicit time evolution.
11+
u: new temperature field
12+
u_previous: previous field
13+
a: diffusion constant
14+
dt: time step. """
15+
16+
n, m = u.shape
17+
18+
for i in range(1, n-1):
19+
for j in range(1, m-1):
20+
u[i, j] = u_previous[i, j] + a * dt * ( \
21+
(u_previous[i+1, j] - 2*u_previous[i, j] + \
22+
u_previous[i-1, j]) / dx2 + \
23+
(u_previous[i, j+1] - 2*u_previous[i, j] + \
24+
u_previous[i, j-1]) / dy2 )
25+
u_previous[:] = u[:]
26+
27+
def iterate(field, field0, a, dx, dy, timesteps, image_interval):
28+
"""Run fixed number of time steps of heat equation"""
29+
30+
dx2 = dx**2
31+
dy2 = dy**2
32+
33+
# For stability, this is the largest interval possible
34+
# for the size of the time-step:
35+
dt = dx2*dy2 / ( 2*a*(dx2+dy2) )
36+
37+
for m in range(1, timesteps+1):
38+
evolve(field, field0, a, dt, dx2, dy2)
39+
if m % image_interval == 0:
40+
write_field(field, m)
41+
42+
def init_fields(filename):
43+
# Read the initial temperature field from file
44+
field = np.loadtxt(filename)
45+
field0 = field.copy() # Array for field of previous time step
46+
return field, field0
47+
48+
def write_field(field, step):
49+
plt.gca().clear()
50+
plt.imshow(field)
51+
plt.axis('off')
52+
plt.savefig('heat_{0:03d}.png'.format(step))
53+
54+

interface/c/heat_main.py

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
from __future__ import print_function
2+
import time
3+
import argparse
4+
5+
from heat import init_fields, write_field, iterate
6+
7+
8+
def main(input_file='bottle.dat', a=0.5, dx=0.1, dy=0.1,
9+
timesteps=200, image_interval=4000):
10+
11+
# Initialise the temperature field
12+
field, field0 = init_fields(input_file)
13+
14+
print("Heat equation solver")
15+
print("Diffusion constant: {}".format(a))
16+
print("Input file: {}".format(input_file))
17+
print("Parameters")
18+
print("----------")
19+
print(" nx={} ny={} dx={} dy={}".format(field.shape[0], field.shape[1],
20+
dx, dy))
21+
print(" time steps={} image interval={}".format(timesteps,
22+
image_interval))
23+
24+
# Plot/save initial field
25+
write_field(field, 0)
26+
# Iterate
27+
t0 = time.time()
28+
iterate(field, field0, a, dx, dy, timesteps, image_interval)
29+
t1 = time.time()
30+
# Plot/save final field
31+
write_field(field, timesteps)
32+
33+
print("Simulation finished in {0} s".format(t1-t0))
34+
35+
if __name__ == '__main__':
36+
37+
# Process command line arguments
38+
parser = argparse.ArgumentParser(description='Heat equation')
39+
parser.add_argument('-dx', type=float, default=0.01,
40+
help='grid spacing in x-direction')
41+
parser.add_argument('-dy', type=float, default=0.01,
42+
help='grid spacing in y-direction')
43+
parser.add_argument('-a', type=float, default=0.5,
44+
help='diffusion constant')
45+
parser.add_argument('-n', type=int, default=200,
46+
help='number of time steps')
47+
parser.add_argument('-i', type=int, default=4000,
48+
help='image interval')
49+
parser.add_argument('-f', type=str, default='bottle.dat',
50+
help='input file')
51+
52+
args = parser.parse_args()
53+
54+
main(args.f, args.a, args.dx, args.dy, args.n, args.i)
55+

0 commit comments

Comments
 (0)