0

I am new using python and I would like to ask you a problem that I have with my current code. I am solving a partial differential equation (1D in space) and I want to make an animation at each time for the given numerical solution, but I don't want to save all the arrays of the solution at each time (because this is not efficient)

For simplicity I just show you the analytical solution of the differential equation.

I have tried to make a plot for each time steep trying to make an animation, but as I have read in other places it's not too much efficient due to the plt.pause()

import numpy as np
import math
from matplotlib import pyplot as plt

pi = math.pi
xmin = 0.0
xmax = 10.0
N = 100 #number of points
x = np.arange(xmin, xmax , (xmax-xmin)/N)

def solution(t):
    p = np.exp(-x**2/(4*k*t))/(np.sqrt(4.*pi*k*t))
    return p

t_final = 10.0
t_initial = 0.0
t = t_initial
dt = 0.1
k = 1.0
while t<t_final:
    t +=dt
    pp = solution(t)

    plt.ion()
    plt.xlabel('x')
    plt.ylabel('P')
    plt.plot(x, pp, 'r-',label = "t=%s" % t)
    plt.legend(loc='upper right')
    plt.draw()
    plt.pause(10**(-20))
    plt.show()
    plt.clf()

Do you know how can be re-implemented my code to make an animation (and save it) without save the data ?

2
  • I would recommend using a FuncAnimation. Commented Jan 31, 2019 at 15:56
  • I see, seems the thing that I am looking for, but how can be implemented in my code? Commented Jan 31, 2019 at 16:24

2 Answers 2

3

Here is how to use FuncAnimation to generate the desired animation

import numpy as np
import math
from matplotlib import pyplot as plt

pi = math.pi
xmin = 0.0
xmax = 10.0
N = 100 #number of points
x = np.arange(xmin, xmax , (xmax-xmin)/N)

t_initial = 0.0
t_final = 10.0
dt = 0.1
k = 1.0

fig, ax = plt.subplots()
ax.set_xlabel('x')
ax.set_ylabel('P')
plotLine, = ax.plot(x, np.zeros(len(x))*np.NaN, 'r-')
plotTitle = ax.set_title("t=0")
ax.set_ylim(0,1.)
ax.set_xlim(xmin,xmax)


def solution(t):
    p = np.exp(-x**2/(4*k*t))/(np.sqrt(4.*pi*k*t))
    return p


def animate(t):
    pp = solution(t)
    plotLine.set_ydata(pp)
    plotTitle.set_text(f"t = {t:.1f}")
    #ax.relim() # use if autoscale desired
    #ax.autoscale()
    return [plotLine,plotTitle]



ani = animation.FuncAnimation(fig, func=animate, frames=np.arange(t_initial, t_final+dt, dt), blit=True)
plt.show()

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

0

This way uses a library I wrote, celluloid. With it I only had to change a handful of lines from your code: mainly the few calls with celluloid and changing the legend creation slightly.

import numpy as np
import math
from matplotlib import pyplot as plt
from celluloid import Camera

pi = math.pi
xmin = 0.0
xmax = 10.0
N = 100 #number of points
x = np.arange(xmin, xmax , (xmax-xmin)/N)


def solution(t):
    p = np.exp(-x**2/(4*k*t))/(np.sqrt(4.*pi*k*t))
    return p


t_final = 10.0
t_initial = 0.0
t = t_initial
dt = 0.1
k = 1.0
fig = plt.figure()
camera = Camera(fig)
plt.xlabel('x')
plt.ylabel('P')
while t<t_final:
    t +=dt
    pp = solution(t)

    line = plt.plot(x, pp, 'r-')
    plt.legend(line, ['t={:.1f}'.format(t)], loc='upper right')
    camera.snap()
animation = camera.animate()
animation.save('animation.mp4')

Comments

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.