1

I am trying to solve the heat equation numerically and to visualize the solution in real time using color mapping. Howver, the colors in the map are not updated. What is the reason? this is the code:

from __future__ import division
from pylab import *

dx, dy = 0.01, 0.01
D = 0.01
dx2, dy2 = dx**2 ,dy**2
dt = (dx2*dy2)/(2*D*(dx2+dy2))
endt = 0.1
Nt = int (endt/dt)
endX,endY = 1,1
nx, ny = int(endX/dx), int(endY/dy)
T = zeros([nx,ny])
Tcopy = zeros([nx,ny])
"""initial conditions"""

for i in range(nx):
 for j in range(ny):
  if( ((i*dx - 0.5)**2 +(j*dy - 0.5)**2 < 0.1) and ((i*dx - 0.5)**2 +(j*dy - 0.5)**2 >0.05) ):
   T[i][j] = 10


def integrate(T,Tcopy):

 T[1:-1, 1:-1] = Tcopy[1:-1, 1:-1] + D*dt*( (Tcopy[2:, 1:-1] - 2*Tcopy[1:-1, 1:-1] + T[:-2, 1:-1])/dx2 + (Tcopy[1:-1, 2:] - 2*Tcopy[1:-1, 1:-1] + T[1:-1, :-2])/dy2  )
 Tcopy = copy(T)
 return Tcopy,T

x = arange(0, endX, dx)
y = arange(0, endY, dy)
X,Y = meshgrid(x, y)

"""creating the plot"""

fig, ax_lst = plt.subplots(1, 1)
im = ax_lst.imshow(T, interpolation='nearest',
                            origin='bottom',
                            aspect='auto',
                            vmin=np.min(T),
                            vmax=np.max(T),
                            cmap='hot',extent=[0,1,0,1])
fig.colorbar(im)

"""main loop"""

for t in range(Nt):
 im.set_data(T)
 plt.draw()
 plt.pause(0.1)
 Tcopy,T = integrate(T,Tcopy)
user1767774
  • 1,775
  • 3
  • 24
  • 32
  • 1
    What do you mean 'colors in the map'? Do you want to change the limits of color bar? – tacaswell Apr 14 '13 at 04:09
  • 1
    The code seems to work fine for me, I see the ring spread and cool over time. – tacaswell Apr 14 '13 at 04:16
  • at any tine I want to see the temperatures in different areas by color (cooler area, darker colors). Right now, not only the limits of the color bar are not changes (I don't want it to change) but also the colors are not changed at all during the simulation. If the value of T at some point changes from 100 to 10 I expect to see a change in the color of that area, but it does not happen. It's all the same red from the beginning to the end. If, however, I create 2 different plots, without animation, one in the beginning and one on the end, one can notice the color differences between the two. – user1767774 Apr 14 '13 at 04:22
  • 1
    set `vmax=5` in `imshow`. The colors _are_ changing (at least on my machine), but it is subtle enough it it hard to see. – tacaswell Apr 14 '13 at 04:39
  • If you want to be sure, add a `savefig` to the loop and save a snap shot at each frame. – tacaswell Apr 14 '13 at 04:51

2 Answers2

2

If you want the range that the colorbar represents to change each frame of animation, then modify your for loop as follows:

for t in range(Nt):
 im.set_data(T)
 im.set_clim(T.min(),T.max())
 plt.draw()
 plt.pause(0.1)
 Tcopy,T = integrate(T,Tcopy)
mtadd
  • 2,495
  • 15
  • 18
  • Thank you! how can I update the colors in the map, without updating the colorbar? I want to maintain the same color range all over the simulation. – user1767774 Apr 14 '13 at 04:29
  • 1
    You'll have to create your own colormap. Check out pydoc for matplotlib.colors.LinearSegmentedColormap and reference [http://stackoverflow.com/questions/9893440/python-matplotlib-colormap](here) on StackOverflow. You can assign the colormap using the `set_cmap` method of your AxesImage instance above. – mtadd Apr 14 '13 at 05:22
1

Compare the left and right:

from __future__ import division
from pylab import *

dx, dy = 0.01, 0.01
D = 0.01
dx2, dy2 = dx**2 ,dy**2
dt = (dx2*dy2)/(2*D*(dx2+dy2))
endt = 0.1
Nt = int (endt/dt)
endX,endY = 1,1
nx, ny = int(endX/dx), int(endY/dy)
T = zeros([nx,ny])
Tcopy = zeros([nx,ny])
"""initial conditions"""

for i in range(nx):
 for j in range(ny):
  if( ((i*dx - 0.5)**2 +(j*dy - 0.5)**2 < 0.1) and ((i*dx - 0.5)**2 +(j*dy - 0.5)**2 >0.05) ):
   T[i][j] = 10


def integrate(T,Tcopy):

 T[1:-1, 1:-1] = Tcopy[1:-1, 1:-1] + D*dt*( (Tcopy[2:, 1:-1] - 2*Tcopy[1:-1, 1:-1] + T[:-2, 1:-1])/dx2 + (Tcopy[1:-1, 2:] - 2*Tcopy[1:-1, 1:-1] + T[1:-1, :-2])/dy2  )
 Tcopy = copy(T)
 return Tcopy,T

x = arange(0, endX, dx)
y = arange(0, endY, dy)
X,Y = meshgrid(x, y)

"""creating the plot"""

fig, ax_lst = plt.subplots(1, 2)
ax_lst[0].imshow(T, interpolation='nearest',
                            origin='bottom',
                            aspect='auto',
                            vmin=np.min(T),
                            vmax=np.max(T),
                            cmap='hot',extent=[0,1,0,1])
im = ax_lst[1].imshow(T, interpolation='nearest',
                            origin='bottom',
                            aspect='auto',
                            vmin=np.min(T),
                            vmax=np.max(T),
                            cmap='hot',extent=[0,1,0,1])
fig.colorbar(im)

"""main loop"""

for t in range(Nt):
 im.set_data(T)
 plt.draw()
 plt.pause(0.1)
 Tcopy,T = integrate(T,Tcopy)
 print np.mean(T), np.max(T), np.min(T)

The colors are changing (at least on my machine), just that it is subtle enough it is hard to see.

You might want to try a log scale as well

im = ax_lst.imshow(T, interpolation='nearest',
                        origin='bottom',
                        aspect='auto',
                        vmin=np.min(T) + .01, # so 0 doesn't blow up the log
                        vmax=np.max(T),
                        cmap='hot',extent=[0,1,0,1],
                        norm=matplotlib.colors.LogNorm(clip=True),)
tacaswell
  • 84,579
  • 22
  • 210
  • 199