I am currently employing a centered finite difference method to simulate the excitation of a circular membrane by a forcing term in Python, and the code is functioning as intended. To further enhance the simulation, I am considering the incorporation of a 3D Fourier transform. This would allow me to analyze the response of the circular membrane at different frequencies, such as when the frequency is set to 257, to observe the excitation of specific normal modes.
Could you provide guidance on calculating and plotting the 3D Fourier transform in Python for this purpose?
This is the array where the wave data is being stored
u = np.zeros((N_steps, Nr, N_phi)) and this is my code
import numpy as np from scipy.special import jn_zeros import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation #%% Parameters Nr = 50 N_phi = 50 N_steps = 10000 radius = 1 c = 10 dphi = 2*np.pi/N_phi dr = radius/Nr dt = 0.0001 CFL=c**2*dt/min(dr,dphi) print(CFL) #%% Initial conditions r = np.linspace(0, radius, Nr) phi = np.linspace(0, 2*np.pi, N_phi) R, phi = np.meshgrid(r, phi) X = R*np.cos(phi) Y = R*np.sin(phi) #%% MODE 01 m=0 n=1 frec= jn_zeros(m, n)[n-1]*c/radius print("la frecuencia es",frec,"modo",m,n) #frec=257 #%% Stepping u = np.zeros((N_steps, Nr, N_phi)) k1 = (c*dt)**2/dr**2 for t in range(0, N_steps-1): for i in range(0, Nr-1): for j in range(-1, N_phi-1): ri = max(r[i], 0.5*dr) # To avoid the singularity at r=0 k2 = (c*dt)**2/(2*ri*dr) k3 = (c*dt)**2/(dphi*ri)**2 u[t+1, i, j] = 2*u[t, i, j] - u[t-1, i, j] \ + k1*(u[t, i+1, j] - 2*u[t, i, j] + u[t, i-1, j])\ + k2*(u[t, i+1, j] - u[t, i-1, j])\ + k3*(u[t, i, j+1] - 2*u[t, i, j] + u[t, i, j-1]) if i==12 and j==29: u[t+1,i,j]=u[t+1,i,j]+1/5*np.sin(frec*dt*t) #%% Plot 11 fig = plt.figure() ax = fig.add_subplot(111, projection='3d') Z = u[999] # Or choose another time step to visualize # Crece hasta 150 maximo en 610 # Recien en 900 empieza a cambiar el sentido ax.plot_surface(X.T, Y.T, Z, cmap='viridis') ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') plt.show() #%% Animation fig = plt.figure() ax3d = fig.add_subplot(111, projection='3d') # Inicializa la superficie 3D Z_3d = u[0] surf = [ax3d.plot_surface(X.T, Y.T, Z_3d, cmap='viridis')] # Set Z-axis limits u_flat = u.flatten() maximo= np.max(u_flat) minimo=np.min(u_flat) if abs(maximo)<=abs(minimo): ax3d.set_zlim(-maximo, maximo) else: ax3d.set_zlim(-maximo, maximo) ax3d.set_zlim(-200, 200) #ax3d.set_title("Frecuencia{} ".format(frec)) ax3d.set_xlabel('X') ax3d.set_ylabel('Y') ax3d.set_zlabel('Z') ax3d.view_init(azim=70, elev=13) # Function that animates def update(i): index = i * 10 if index < len(u): Z_3d = u[index] surf[0].remove() surf[0] = ax3d.plot_surface(X.T, Y.T, Z_3d, cmap='viridis') ani = FuncAnimation(fig, update, frames=range(N_steps), interval=10, blit=False, repeat=False) plt.show() I tried this
#%% Sección de FFT from scipy.signal import find_peaks FS= np.fft.fftn(u) # Calculate the magnitude spectrum along each axis fouriertime = np.abs(FS.sum(axis=(1, 2))) plt.plot(fouriertime) plt.title('Transforamda temporal'), plt.xlabel('Time Step') subfouriertime =fouriertime[:300] # Find peaks in the subset peaks, _ = find_peaks(subfouriertime) # Plot the spectrum with identified peaks plt.figure() plt.plot(subfouriertime, label='Temporal Transform') plt.plot(peaks, subfouriertime[peaks], 'x', label='Peaks > 0.2e7') plt.xlabel('Time Step') plt.ylabel('Magnitude') plt.legend() plt.show() But as you see, I do not get a peak at 24.04 hz which is the frequency of mode 01.
I know that me code is not the best but I am new with these simulations.
This is the result of the Fourier transform
And if someone is wondering what is the result of the wave propagation:





