Solving one-dimensional wave equation by finite difference method (python)

Simple wave equation

 \frac{\partial^2 u}{\partial t^2} = c^2 \frac{\partial^2 u}{\partial x^2} \\
0<x<l,0<t

I want to solve this

boundary condition

u(0)=0,\frac{\partial u}{\partial x}\Big|_{x=l} = 0

The left end is the Dirichlet boundary condition that specifies the value of $ u $ at the boundary, and the right end is the Neumann boundary condition that specifies the derivative value of the boundary value.

The boundary condition is that the left is the fixed end and the right is the free end.

Initial conditions

u(x,0) = f(x)\\
\frac{\partial u}{\partial t}=0

If it is the vibration of a string or the vibration of a vertical bar, the initial velocity is 0.

Discrete

x_i = i\Delta x\\
t^n = n\Delta t\\
u_{i}^n = u(x_i,t^n)\\
(i = 1\cdots m, \Delta x = \frac{l}{m})

And put. However, $ m $ is the number of spatial divisions.

Initial condition Boundary condition

First, set the initial solution.

u_{i}^0 = f(x_i)\\
u_{i}^1 = u_{i}^0

Since the first derivative of time is 0, $ u_ {i} ^ 1 = u_ {i} ^ 0 $.

Next, set the boundary conditions. However, the trouble is that the Neumann boundary condition at the right end is expressed by the spatial derivative, so two elements must be used to express it. Therefore, add another false element to the rightmost boundary. In other words

u_{m+1}^n = u_{m}^n

If so, the Neumann boundary condition at the right end, that the first-order spatial derivative is 0, is satisfied. The leftmost Dirichlet boundary condition can be expressed as follows.

u_1^n = 0

Finally, the equation itself is discretized.

Discretization of spatial differentiation

\frac{\partial^2 u}{\partial x^2}\Big|_{x=x_i}=\frac{u_{i+1}-2u_{i}+u_{i-1}}{\Delta x^2}

This can be derived by Taylor-expanding $ u_ {i + 1} $ and $ u_ {i-1} $ with $ x = x_i $.

Discretization of time evolution

Thinking in the same way as spatial differentiation,

\frac{\partial^2 u}{\partial t^2} =\frac{u^{n+1}-2u^{n}+u^{n-1}}{\Delta t^2}

Because it is

\begin{align}
u^{n+1}_i &= 2u^{n}_i-u^{n-1}_i + \Delta t^2 \frac{\partial^2 u}{\partial t^2}\Big|_{x=x_i}\\
&= 2u^{n}_i-u^{n-1}_i + c^2 \Delta t^2 \frac{u_{i+1}-2u_{i}+u_{i-1}}{\Delta x^2}
\end{align}

Let's write the code

Sample fucking code

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from copy import deepcopy


fig, ax = plt.subplots()

c = 1.
x_left = 0.
x_right = 1.
t = 0.
#Meaning to discretize at 101 points
num_points = 101
dx = (x_right-x_left)/(num_points-1)
#Reserve one extra for Neumann boundary
x = np.linspace(x_left, x_right+dx, num_points+1)
# u = x/Initialize at 1000
u = 1e-3*x
#Neumann boundary conditions
u[-1] = u[-2]

u_before = deepcopy(u)
u_next = deepcopy(u)

#Accumulate the value of u at regular intervals here
u_at_t = [deepcopy(u)]


dt = 0.1 * dx/c

count = 0


while t < 0.5:
    print(np.diff(u,2))
    u_next[1:num_points] = 2.*u[1:num_points] - u_before[1:num_points] + c*c*dt*dt/(dx*dx) * np.diff(u, 2)

    #Neumann boundary conditions
    u_next[-1] = u_next[-2]
    u_next[0] = 0.
    u_before = deepcopy(u)
    u = deepcopy(u_next)
    u_next = np.zeros(u.shape)
    t += dt
    count += 1
    #Once every 16 steps
    if count == 16:
        u_at_t.append(deepcopy(u))
        count = 0


def update(u, x):
    plt.clf()
    plt.xlim(x_left, x_right)
    plt.ylim(-1e-3, 1e-3)
    plt.plot(x, u)


#Function for displaying animation
anim = FuncAnimation(fig, update, fargs=(
    x,), frames=u_at_t, interval=10)

plt.show()

# anim.save("foo.mp4", writer="ffmpeg",fps=10)

Note that saving a video can be a heavy task

Continue

reference

Techniques for making videos https://qiita.com/msrks/items/e264872efa062c7d6955 Difference formula https://qiita.com/Ushio/items/0249fd7a5363ccd914dd

Recommended Posts

Solving one-dimensional wave equation by finite difference method (python)
[Scientific / technical calculation by Python] Solving one-dimensional Newton equation by the 4th-order Runge-Kutta method
[Scientific / technical calculation by Python] Solving one-dimensional Schrodinger equation in stationary state by shooting method (1), well-type potential, quantum mechanics
[Scientific / technical calculation by Python] Solving one-dimensional Schrodinger equation in stationary state by shooting method (2), harmonic oscillator potential, quantum mechanics
Python --Differential equation numerical solution Euler method & central difference method & Runge-Kutta method
[Numerical calculation method, python] Solving ordinary differential equations by Eular method
[Python] Difference between function and method
[Python] Difference between class method and static method
Finite element method beginning (one-dimensional element stiffness matrix)
Alignment algorithm by insertion method in Python
[Scientific / technical calculation by Python] Solving second-order ordinary differential equations by Numerov method, numerical calculation
[Scientific / technical calculation by Python] Numerical solution of one-dimensional and two-dimensional wave equations by FTCS method (explicit method), hyperbolic partial differential equations
Solving the equation of motion in Python (odeint)
[Python] Numerical calculation of two-dimensional thermal diffusion equation by ADI method (alternate direction implicit method)