1

I'm trying to compare several numerical schemes with exact solution of a PDE. To do that, I'm trying to make an animation, in which there are multiple subplots and each subplot has two functions evolving. (numerical and exact)

I found out how to make multiple lines animating here, Matplotlib multiple animate multiple lines

And I also found out how to make multiple subplots. animated subplots using matplotlib

But I'm not sure how to do both. They looks so confusing when looked together (I'm not that familiar with matplotlib, especially FuncAnimation) And also I want to make a subplot number as variable, so user can input any number of functions.

my code is this. Currently this code generates plot for each numerical scheme, but I want it to make only one plot. So the 'plot' function would be called only once,

plot(*arguments, FTCS, upwind, anotherfunc, anotherfunc2, ...)

this way.

Sorry for the messy code. I attached all of them just to make a minimum working example. Only 'plot' function is relevant to my question.

*edited code.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation



#dt=1/5
dx=1/400
tm=9
xm=1
C=0.8
u=.1
dt=dx*C/u
arguments=dt,dx,tm,xm,C

def plot(dt,dx,tm,xm,C,*funcs):
    plt.figure()
    fig,axes=plt.subplots(len(funcs))
    i=1
    for ax,func in zip(axes, funcs):
    #    plt.subplot(len(funcs),1,i)
        x1,T1=func(dt,dx,tm,xm,C)
        plotlays, plotcols = [2], ["black","red"]
        lines = []
        ax=plt.axes(xlim=(0,1),ylim=(-1.1,1.1))
        line,=ax.plot([],[],lw=2)
        for index in range(2):
            lobj = ax.plot([],[],lw=2,color=plotcols[index])[0]
            lines.append(lobj)

        def init():
            for line in lines:
                line.set_data([],[])
            return lines

        def animate(i):
            x=x1
            y=T1[i]
            y2=T2[i]
            xlist=[x,x]
            ylist=[y,y2]

            for lnum,line in enumerate(lines):
                line.set_data(xlist[lnum],ylist[lnum])
            return lines

        anim=animation.FuncAnimation(fig,animate,init_func=init,frames=np.shape(T1)[0],interval=20,blit=False)

        plt.title('%s' % func.__name__)
        plt.xlabel('x')
        plt.ylabel('T')
        i+=1

    plt.show()



    return



def finit(x):
    if 0<=x<=.1:
        return np.sin(10*np.pi*x)
    else:
        return 0

def FTCS(dt,dx,tm,xm,C):
    x=np.arange(0,xm+dx,dx)
    t=np.arange(0,tm+dt,dt)
    lx=len(x)
    lt=len(t)
    T=np.zeros([lt,lx])
    for i in range(0,lx):
        T[0,i]=finit(x[i])
    for n in range(0,lt-1):
        for j in range(1,lx-1):
            T[n+1,j]=T[n,j]-.5*C*(T[n,j+1]-T[n,j-1])
    return x,T

def upwind(dt,dx,tm,xm,C):
    x=np.arange(0,xm+dx,dx)
    t=np.arange(0,tm+dt,dt)
    lx=len(x)
    lt=len(t)
    T=np.zeros([lt,lx])
    for i in range(0,lx):
        T[0,i]=finit(x[i])
    for n in range(0,lt-1):
        for j in range(1,lx-1):
            T[n+1,j]=(1-C)*T[n,j]+C*T[n,j-1]
    return x,T

def exact(dt,dx,tm,xm,C):
    x=np.arange(0,xm+dx,dx)
    t=np.arange(0,tm+dt,dt)
    u=C*dx/dt
    T=np.zeros([len(t),len(x)])
    for n in range(0,len(t)):
        for j in range(0,len(x)):
            if u*t[n]<x[j]<=u*t[n]+.1:
                T[n,j]=np.sin(10*np.pi*(x[j]-u*t[n]))
            else: T[n,j]=0
    return T

plot(*arguments,FTCS,upwind)
4
  • Let your plot function take a list of functions plot(..., funcs=[func1, func2,..]). Create as many axes as you have functions, fig, axes = plt.subplots(len(funcs)). Then iterate over the functions and axes, for ax, func in zip(axes, funcs): Do so for creating the lines as well as when animating them. Commented Feb 24, 2019 at 5:18
  • @ImportanceOfBeingErnest I'm sorry but it doesn't work. It only shows the animation of the last function. I posted edited code. Did I do it right? I'm not sure which portion of code I should put in loop and which I shouldn't. Commented Feb 24, 2019 at 23:07
  • I think anim=animation.FuncAnimation(fig,animate,init_func=init,frames=np.shape(T1)[0],interval=20,blit=False) This part is problem, because fig refers to the whole figure. But I cannot put it out of loop because I made animate for each axes. Commented Feb 24, 2019 at 23:11
  • Neither the animation, nor the functions should be inside the loop. Rather you'd have a loop inside the animating function. Commented Feb 25, 2019 at 3:52

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.