81 lines
2.9 KiB
Python
81 lines
2.9 KiB
Python
import numpy as np
|
|
import matplotlib.pyplot as plt
|
|
import time, sys
|
|
from matplotlib import cm
|
|
|
|
"""
|
|
Simulation comments :
|
|
As we increase the number of grid points, the solution tends to a hat that
|
|
have move to the right.
|
|
For nx<50, we have a bell not fully developed.
|
|
For nx=50, we have something ike a perfect bell.
|
|
For nx>50, we go back to the hat function.
|
|
|
|
For big dt, ~0.25,we have divergence of data.
|
|
Neverthe less, if we increase the timestep x2, we obtain a better solution
|
|
even if the number of grid points stays lower.
|
|
|
|
There seems to be some numerical diffusion problem, for high number of grid points
|
|
the solution seems more like a transitory phenomena that diverges greatly !
|
|
For more information about this read about courant number.
|
|
"""
|
|
|
|
nx = 41 # Number of grid points.
|
|
ny = 41
|
|
nt = 50 # Number of timesteps we want to calculate.
|
|
c = 1 # Assume wavespeed of c = 1.
|
|
dx = 2 / (nx-1) # Distance between any pair of adjacent grid points.
|
|
dy = 2 / (ny-1) # Distance between any pair of adjacent grid points.
|
|
sigma = 0.2
|
|
dt = sigma*dx # Amount of time each timesteps covers (delta t)
|
|
|
|
x = np.linspace(0,2,nx)
|
|
y = np.linspace(0,2,ny)
|
|
|
|
# Boundary conditions.
|
|
# Starting all values as 1 m/s.
|
|
u = np.ones((nx,ny))
|
|
|
|
# Setting u = 2 between 0.5 and 1 as per out initial conditions.
|
|
u[int(0.5 / dy):int(1 / dy + 1),int(0.5 / dx):int(1 / dx + 1)] = 2
|
|
|
|
# Generating two grids one for the values of x, another for the values of y. This will be needed for the plotting function.
|
|
X,Y = np.meshgrid(x,y)
|
|
|
|
# Plot initial conditions.
|
|
# Initialize the figure window. figsize and dpi are optional and specify size and resolution respectively.
|
|
fig, ax = plt.subplots(figsize=(11,7), dpi=100)
|
|
# Assigns the plot window and the axes label 'ax' also specifies 3d projection plot.
|
|
ax = plt.subplot(1,2,1, projection='3d')
|
|
#ax = fig.gca(projection='3d')
|
|
# Equivalent to the regular plot command, but it takes grid of X,Y values for data point positions.
|
|
surf = ax.plot_surface(X, Y, u[:], cmap=cm.viridis)
|
|
|
|
|
|
# Temporary array for the solutions.
|
|
un = np.ones(nx)
|
|
|
|
for n in range(nt+1): # Loop for values of n from 0 to nt.
|
|
un = u.copy() # Copy the existing values of u into un.
|
|
row, col = u.shape
|
|
for i in range(1, row): # Loop for values in u from 1 to nx.
|
|
for j in range(1,col):
|
|
u[j,i] = un[j,i] - c * dt / dx * (un[j,i] - un[j,i-1]) - c * dt / dx * (un[j,i] - un[j-1,i])
|
|
|
|
# Boundary conditions
|
|
u[0,:] = 1
|
|
u[-1,:] = 1
|
|
u[:,0] = 1
|
|
u[:,-1] = 1
|
|
|
|
# Assigns the plot window and the axes label 'ax' also specifies 3d projection plot.
|
|
ax = plt.subplot(1,2,2, projection='3d')
|
|
#ax = fig.gca(projection='3d')
|
|
# Equivalent to the regular plot command, but it takes grid of X,Y values for data point positions.
|
|
surf = ax.plot_surface(X, Y, u[:], cmap=cm.viridis)
|
|
# rotate the axes and update
|
|
for angle in range(0, 360):
|
|
ax.view_init(30, angle)
|
|
plt.draw()
|
|
plt.pause(.001)
|